Qlik Community

Qlik Brasil

Group community for Brazil users. discussion only in Portuguese.

Highlighted
guilhermedorow
New Contributor II

Dificuldades com Inner Join

Olá!

Sou iniciante no qlik e tenho uma dúvida que não consegui solucionar sozinho até o presente momento.

Estou montando uma análise para avaliar a quantidade de produtos produzidos, abaixo está o sql que montei e extrai tudo perfeitamente mas no qlik não consigo relacionar as tabelas corretamente com o inner join.

No qlik criei uma tabela Fato para a minha tabela PRODUCAO e nessa tabela eu tenho apenas os códigos, as descrições ficam separadas nas outras tabelas, por isso a necessidade do inner join.

Tentei ligar direto, relacionando por exemplo código sub grupo da tabela producao com o código sub grupo da tabela subgrupo_01 porém o problema é que, o subgrupo 001 é feijão quando está no grupo 001 e sorvete quando está no grupo 002. O mesmo problema ocorre com o item, por isso a necessidade desse relacionamento abaixo.

Vocês conseguem me dar uma luz de como posso proceder com esse relacionamento?

OBS.: montei uma visualização só com os códigos (apenas com a tabela producao) sem as descrições e ficou perfeita, quando relaciono com as demais tabelas para trazer a descrição que embaralha tudo.

SELECT  PRO.COD_OPERADOR,

       USR.NOME_OPERADOR,

        PRO.NIVEL,

        PRO.GRUPO,

        PRO.SUBGRUPO,

       SUB.DESCR_SUBGR,

        PRO.ITEM,

       ITE.NARRATIVA,

       COL.COLECAO,

       COL.DESCR_COLECAO,

        PRO.NOTA_ENTRADA,

        PRO.SERIE_NOTA,

        PRO.CNPJ9_FORN,

        PRO.CNPJ4_FORN,

        PRO.CNPJ2_FORN,

       FRN.NOME_FORNECEDOR,

        PRO.DATA_PRODUCAO,

        PRO.PESO

      

  FROM PRODUCAO  PRO

   

    INNER JOIN GRUPO_01 GRU ON (GRU.NIVEL =  PRO.NIVEL AND

                                GRU.REFERENCIA      =  PRO.GRUPO)

   

    INNER JOIN SUBGRUPO_01 SUB ON (SUB.NIVEL_S =  PRO.NIVEL AND

                                SUB.GRUPO_S =  PRO.GRUPO   AND

                                SUB.SUBGRUPO_S      =  PRO.SUBGRUPO)

   

    INNER JOIN ITEM_01 ITE ON (ITE.NIVEL_E  =  PRO.NIVEL  AND

                                ITE.GRUPO_E  =  PRO.GRUPO    AND

                                ITE.SUBGRU_E =  PRO.SUBGRUPO AND

                                ITE.ITEM_E   =  PRO.ITEM)

   

    INNER JOIN COL_01 COL ON (COL.COLECAO = GRU.COLECAO)

   

    INNER JOIN FORNE_01 FRN ON (FRN.FORNECEDOR9 =  PRO.CNPJ9_FORN AND

                                FRN.FORNECEDOR4 =  PRO.CNPJ4_FORN AND

                                FRN.FORNECEDOR2 =  PRO.CNPJ2_FORN)

    INNER JOIN OPERADOR_01 USR ON (USR.CODIGO_USUARIO =  PRO.COD_OPERADOR)

WHERE  PRO.DATA_PRODUCAO BETWEEN

      TO_DATE('11/05/2016', 'DD/MM/YYYY') --Data inicial

  AND TO_DATE('11/05/2016', 'DD/MM/YYYY') --Data final

 

GROUP BY

        PRO.COD_OPERADOR,

        USR.NOME_OPERADOR,

        PRO.NIVEL,

        PRO.GRUPO,

        PRO.SUBGRUPO,

       SUB.DESCR_SUBGR,

       PRO.ITEM,

       ITE.NARRATIVA,

       COL.COLECAO,

       COL.DESCR_COLECAO,

        PRO.NOTA_ENTRADA,

        PRO.SERIE_NOTA,

        PRO.CNPJ9_FORN,

        PRO.CNPJ4_FORN,

        PRO.CNPJ2_FORN,

        FRN.NOME_FORNECEDOR,

        PRO.DATA_PRODUCAO,

        PRO.PESO

Desde já agradeço a todos da comunidade

1 Solution

Accepted Solutions
wellington1978
New Contributor III

Re: Dificuldades com Inner Join

    Guilherme,

    Saúde e Paz!

    Uma das alternativas é concatenar os campos chaves para criar um único campo de ligação. Veja minha sugestão de como ficaria seu Script com essa alternativa:

LOAD *, NUM(GRUPO, '00')&'|'&NUM(SUBGRUPO, '00') AS ID_CLASSE;
SQL
SELECT
PRO.COD_OPERADOR,
USR.NOME_OPERADOR,
PRO.NIVEL,
PRO.GRUPO,
PRO.SUBGRUPO,
SUB.DESCR_SUBGR,
PRO.ITEM,
ITE.NARRATIVA,
COL.COLECAO,
COL.DESCR_COLECAO,
PRO.NOTA_ENTRADA,
PRO.SERIE_NOTA,
PRO.CNPJ9_FORN,
PRO.CNPJ4_FORN,
PRO.CNPJ2_FORN,
FRN.NOME_FORNECEDOR,
PRO.DATA_PRODUCAO,
PRO.PESO
FROM
PRODUCAO PRO
INNER JOIN GRUPO_01 GRU
ON
GRU.NIVEL        = PRO.NIVEL
AND GRU.REFERENCIA = PRO.GRUPO
INNER JOIN SUBGRUPO_01 SUB
ON
SUB.NIVEL_S      = PRO.NIVEL
AND SUB.GRUPO_S    = PRO.GRUPO
AND SUB.SUBGRUPO_S = PRO.SUBGRUPO
INNER JOIN ITEM_01 ITE
ON
ITE.NIVEL_E    = PRO.NIVEL
AND ITE.GRUPO_E  = PRO.GRUPO
AND ITE.SUBGRU_E = PRO.SUBGRUPO
AND ITE.ITEM_E   = PRO.ITEM
INNER JOIN COL_01 COL
ON
COL.COLECAO = GRU.COLECAO
INNER JOIN FORNE_01 FRN
ON
FRN.FORNECEDOR9   = PRO.CNPJ9_FORN
AND FRN.FORNECEDOR4 = PRO.CNPJ4_FORN
AND FRN.FORNECEDOR2 = PRO.CNPJ2_FORN
INNER JOIN OPERADOR_01 USR
ON
USR.CODIGO_USUARIO = PRO.COD_OPERADOR
WHERE
PRO.DATA_PRODUCAO BETWEEN TO_DATE('11/05/2016', 'DD/MM/YYYY') --Data inicial
AND TO_DATE('11/05/2016', 'DD/MM/YYYY')                         --Data final
GROUP BY
PRO.COD_OPERADOR,
USR.NOME_OPERADOR,
PRO.NIVEL,
PRO.GRUPO,
PRO.SUBGRUPO,
SUB.DESCR_SUBGR,
PRO.ITEM,
ITE.NARRATIVA,
COL.COLECAO,
COL.DESCR_COLECAO,
PRO.NOTA_ENTRADA,
PRO.SERIE_NOTA,
PRO.CNPJ9_FORN,
PRO.CNPJ4_FORN,
PRO.CNPJ2_FORN,
FRN.NOME_FORNECEDOR,
PRO.DATA_PRODUCAO,
PRO.PESO;

   Observe que o comando "LOAD *, NUM(GRUPO, '00')&'|'&NUM(SUBGRUPO, '00') AS ID_CLASSE;" vai carregar todos os campos do comando SELECT  e concatenar os campos chaves para formar um único. Você deve usar essa expressão para montar os mesmo campos nas outras tabelas. Assim você acabará com as chaves sintéticas.

    Se sua base de dados for muito grande você poderá usar "autonumber", "autonumberhash128" ou "autonumberhash256" para criar chaves primárias. Mas a primeira ideia que lhe dei torna os campos mais intuitivos.

    Espero ter podido ajudar...

Felicidades...

7 Replies
MVP
MVP

Re: Dificuldades com Inner Join

Guilherme,

normalmente tento trazer into para o Qlik

exemplo:

LOAD

      GRUPO              as Grupo_Codigo;

SELECT  GRUPO  FROM PRODUCAO;

left join

LOAD

      GRUPO              as Grupo_Codigo,

       DES_GRUPO    as Grupo_Descricao;

SELECT  GRUPO , DES_GRUPO FROM GRUPO;

a descrição pode ser pega usando um applymap também......ou com join......

Somente deixo no SQL quando a performance ser muito diferente e ai deixo o banco resolver. Mas na grande maioria do tempo, sempre resolvo no Qlik.  Mas ai depende de cada um.......

guilhermedorow
New Contributor II

Re: Dificuldades com Inner Join

Olá Alessandro,

Obrigado por responder!

Tentei com o left join como você explicou acima, mas ele criou chaves sintéticas e pelo que andei lendo essas chaves sintéticas não são boas de serem criadas certo?

O problema começa no subgrupo e item.

Exemplo abaixo:

bala de goma pertence ao grupo 2 subgrupo 1 e item 1

arroz pertence ao grupo 1 subgrupo 1 e item 1

veja que os produtos acima pertencem ao mesmo subgrupo e item, mas são diferentes. No SQL que coloquei na pergunta está funcionando por isso anexei ele, mas no qlik não consegui relacionar dessa forma.

O Qlik só permite 1 campo de comparação para relacionar as tabelas, por exemplo se eu coloco o campo GRUPO no grupo, no subgrupo e no item ele da erro..

wellington1978
New Contributor III

Re: Dificuldades com Inner Join

    Guilherme,

    Saúde e Paz!

    Uma das alternativas é concatenar os campos chaves para criar um único campo de ligação. Veja minha sugestão de como ficaria seu Script com essa alternativa:

LOAD *, NUM(GRUPO, '00')&'|'&NUM(SUBGRUPO, '00') AS ID_CLASSE;
SQL
SELECT
PRO.COD_OPERADOR,
USR.NOME_OPERADOR,
PRO.NIVEL,
PRO.GRUPO,
PRO.SUBGRUPO,
SUB.DESCR_SUBGR,
PRO.ITEM,
ITE.NARRATIVA,
COL.COLECAO,
COL.DESCR_COLECAO,
PRO.NOTA_ENTRADA,
PRO.SERIE_NOTA,
PRO.CNPJ9_FORN,
PRO.CNPJ4_FORN,
PRO.CNPJ2_FORN,
FRN.NOME_FORNECEDOR,
PRO.DATA_PRODUCAO,
PRO.PESO
FROM
PRODUCAO PRO
INNER JOIN GRUPO_01 GRU
ON
GRU.NIVEL        = PRO.NIVEL
AND GRU.REFERENCIA = PRO.GRUPO
INNER JOIN SUBGRUPO_01 SUB
ON
SUB.NIVEL_S      = PRO.NIVEL
AND SUB.GRUPO_S    = PRO.GRUPO
AND SUB.SUBGRUPO_S = PRO.SUBGRUPO
INNER JOIN ITEM_01 ITE
ON
ITE.NIVEL_E    = PRO.NIVEL
AND ITE.GRUPO_E  = PRO.GRUPO
AND ITE.SUBGRU_E = PRO.SUBGRUPO
AND ITE.ITEM_E   = PRO.ITEM
INNER JOIN COL_01 COL
ON
COL.COLECAO = GRU.COLECAO
INNER JOIN FORNE_01 FRN
ON
FRN.FORNECEDOR9   = PRO.CNPJ9_FORN
AND FRN.FORNECEDOR4 = PRO.CNPJ4_FORN
AND FRN.FORNECEDOR2 = PRO.CNPJ2_FORN
INNER JOIN OPERADOR_01 USR
ON
USR.CODIGO_USUARIO = PRO.COD_OPERADOR
WHERE
PRO.DATA_PRODUCAO BETWEEN TO_DATE('11/05/2016', 'DD/MM/YYYY') --Data inicial
AND TO_DATE('11/05/2016', 'DD/MM/YYYY')                         --Data final
GROUP BY
PRO.COD_OPERADOR,
USR.NOME_OPERADOR,
PRO.NIVEL,
PRO.GRUPO,
PRO.SUBGRUPO,
SUB.DESCR_SUBGR,
PRO.ITEM,
ITE.NARRATIVA,
COL.COLECAO,
COL.DESCR_COLECAO,
PRO.NOTA_ENTRADA,
PRO.SERIE_NOTA,
PRO.CNPJ9_FORN,
PRO.CNPJ4_FORN,
PRO.CNPJ2_FORN,
FRN.NOME_FORNECEDOR,
PRO.DATA_PRODUCAO,
PRO.PESO;

   Observe que o comando "LOAD *, NUM(GRUPO, '00')&'|'&NUM(SUBGRUPO, '00') AS ID_CLASSE;" vai carregar todos os campos do comando SELECT  e concatenar os campos chaves para formar um único. Você deve usar essa expressão para montar os mesmo campos nas outras tabelas. Assim você acabará com as chaves sintéticas.

    Se sua base de dados for muito grande você poderá usar "autonumber", "autonumberhash128" ou "autonumberhash256" para criar chaves primárias. Mas a primeira ideia que lhe dei torna os campos mais intuitivos.

    Espero ter podido ajudar...

Felicidades...

guilhermedorow
New Contributor II

Re: Dificuldades com Inner Join

Wellington,

Muito obrigado!

Fiz conforme você explicou e ficou perfeito! Só fiquei com uma dúvida, com essa forma que você me passou foi criado uma tabela com todas as informações corretas que preciso, e apenas adicionei um calendário conforme figura abaixo:

Capturar.JPG

É Correto trabalhar dessa forma ou você recomendaria manter apenas os campos chaves e relacionar esses campos  com as outras tabelas?

De verdade, muito obrigado!!

wellington1978
New Contributor III

Re: Dificuldades com Inner Join

    Oi Guilherme,

    Fico feliz que tenha funcionado

    É correto sim trabalhar dessa forma. Mas você tem que converter a data num campo de texto para evitar "confusões" por conta dos diversos formatos que um campo de data pode ser interpretado.

   Vou te passar um Scrip de gera um QVD com um calendário completo, marcando os dias úteis ou não. Nele você poderá adicionar os feriados municipais e estaduais que desejar, além de datas comemorativas. Essas informações podem lhe ser muito úteis para cálculos com dia úteis. Eu adaptei esse Script para colocar os feriados com datas móveis. O cálculo é complexo mas é bem rápido pra gerar (meu PC gera um calendário de 4 anos em menos de um segundo). Lá vai

//   Iniciar as variáveis que determinarão o intervalo do calendário
LET V_DATA_INI = MakeDate( Year( Today())-4, 1, 1); 
LET V_DATA_FIN = YearEnd( Today());

LET V_ANO = Year( V_DATA_INI);
LET V_ANO_FIN = Year( V_DATA_FIN);


DIRECTORY;

DO WHILE V_ANO <= V_ANO_FIN


LET V_C01 = Floor( V_ANO/100);
LET V_C02 = V_ANO - (19*Floor( V_ANO /19));
LET V_C03 = Floor((V_C01 - 17)/25);
LET V_C04 = V_C01 - Floor(V_C01/4) - Floor((V_C01-V_C03)/3) +(19*V_C02) + 15;
LET V_C05 = V_C04 - (30*Floor(V_C04/30));
LET V_C06 = V_C05 - (Floor(V_C05/28)*(1-Floor(V_C05/28))*Floor(29/(V_C05+1))*Floor((21-V_C02)/11));
LET V_C07 = V_ANO + Floor(V_ANO/4) + V_C06 + 2 -V_C01 + Floor(V_C01/4);
LET V_C08 = V_C07 - 7*Floor(V_C07/7);
LET V_C09 = V_C06 - V_C08;
LET V_MES = 3 + Floor((V_C09+40)/44);
LET V_DIA = V_C09 + 28 - (31*Floor(V_MES/4));
SET V_Pascoa =  'MakeDate( $(V_ANO), $(V_MES), $(V_DIA))';

FERIADOS:

// Para adicionar um novo feriado insira a linha de comando da seguinte forma: "LOAD  $(V_ANO) & 'MM' & 'DD' as Id_Calendario, 'Nome_do_Feriado' as Feriado AutoGenerate(1);"
// Substituindo MM pelo número do mês e DD pelo dia; ambos com dois algarismos
    
LOAD  $(V_ANO) & Num($(V_MES),'00') & Num($(V_DIA),'00') as Id_Calendario, 'Páscoa' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & Num( Month( $(V_Pascoa) - 47), '00') & Num( Day($(V_Pascoa) - 47), '00') as Id_Calendario, 'Carnaval' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & Num( Month( $(V_Pascoa) - 2), '00') & Num( Day( $(V_Pascoa) - 2), '00') as Id_Calendario, 'Paixão de Cristo' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & Num( Month( $(V_Pascoa) + 60), '00') & Num( Day( $(V_Pascoa) + 60), '00') as Id_Calendario, 'Corpus Cristi' as Feriado AutoGenerate(1);    
LOAD  $(V_ANO) & '01' & '01' as Id_Calendario, 'Confraternização Universal' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '04' & '21' as Id_Calendario, 'Tiradentes' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '05' & '01' as Id_Calendario, 'Dia do Trabalhador' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '09' & '07' as Id_Calendario, 'Independência' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '10' & '12' as Id_Calendario, 'Nossa Senhora Aparecida' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '11' & '02' as Id_Calendario, 'Finados' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '11' & '15' as Id_Calendario, 'Proclamação da República' as Feriado AutoGenerate(1);
LOAD  $(V_ANO) & '12' & '25' as Id_Calendario, 'Natal' as Feriado AutoGenerate(1);

DATAS_COMEMORATIVAS:

// Para adicionar uma nova data comemorativa insira a linha de comando da seguinte forma:
//"LOAD  $(V_ANO) & 'MM' & 'DD' as Id_Calendario, 'Nome_Da_Data_Comemorativa' as Dt_Comemorativa AutoGenerate(1);"
// Substituindo MM pelo número do mês e DD pelo dia; ambos com dois algarismos
    
LOAD  $(V_ANO) & '10' & '30' as Id_Calendario, 'Emancipação Política de Arapiraca' as Dt_Comemorativa  AutoGenerate(1);
LOAD  $(V_ANO) & '09' & '16' as Id_Calendario, 'Emancipação Política de Alagoas' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '02' & '02' as Id_Calendario, 'N.S. do Bom Conselho' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '10' & '17' as Id_Calendario, 'Dia do Eletricista' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '11' & '20' as Id_Calendario, 'Consciência Negra' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '12' & '31' as Id_Calendario, 'Revellion' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '12' & '08' as Id_Calendario, 'N.S. da Conceição' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '06' & '13' as Id_Calendario, 'Santo Antonio' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '06' & '24' as Id_Calendario, 'São João' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '06' & '29' as Id_Calendario, 'São Pedro' as Dt_Comemorativa AutoGenerate(1);
LOAD  $(V_ANO) & '10' & '15' as Id_Calendario, 'Dia dos Professores' as Dt_Comemorativa AutoGenerate(1);

LET V_ANO = V_ANO +1;
LOOP;


Calendario_Temp:
LOAD
//   Date( Data, 'DD/MM/YYYY' ) as Data,
     Data,
Num( Day( Data ), '00' ) as DIA,
Month( Data ) as MES,
Year( Data ) as ANO,
DayNumberOfQuarter( Data ) as [Dia Trimestre],
DayNumberOfYear( Data ) as [Dia Ano],
MonthName( Data ) as [Mes Ano],
QuarterName( Data ) as Quarter,
Week( Data ) as Semana,
Ceil( Month( Data ) / 3 )&'º Trim' as Trimestre,
WeekDay( Data ) as [Dia Semana],
//   ApplyMap( 'MapDias', Text( WeekDay( Data ) ) ) as [N° Dia Semana],
     AutoNumber( Data ) as Sequencial,
If( WeekDay( Data )= 'DOM' or WeekDay( Data )= 'SAB', 0, 1 ) as DiaUtil_Temp,
Year( Data )&Num( Month( Data ), 00 ) as [Ano Mes],
Year( Data )&Num( Month( Data ),'00')&Num( Day( Data ), '00' ) as Id_Calendario;

LOAD
//   Date( MonthEnd( Today() ) - Recno(), 'DD/MM/YYYY' ) as Data
           Date( YearEnd(Today())+1 - Recno()) as Data

AutoGenerate( V_DATA_FIN+1 - V_DATA_INI );

Left Join

LOAD * Resident FERIADOS;

Left Join

LOAD * Resident DATAS_COMEMORATIVAS;

Calendario:
LOAD Data,
DIA,
MES,
ANO,
[Dia Trimestre],
[Dia Ano],
[Mes Ano],
Quarter,
Semana,
Trimestre,
[Dia Semana],
Sequencial,
[Ano Mes],
Id_Calendario,
Feriado,
Dt_Comemorativa
,
If( Len(Feriado),0,DiaUtil_Temp) as DiaUtil;
LOAD * Resident Calendario_Temp;

STORE Calendario into Calendario.qvd (qvd);
//STORE Calendario into .\TRANSFORMACAO\Calendario.qvd (qvd);
//STORE Calendario into \\Servarquivos\Clandestinos_AT\QVDs\Calendario.qvd (qvd);

Drop Tables FERIADOS, DATAS_COMEMORATIVAS, Calendario_Temp, Calendario;



    Adapte para seu uso e se divirta!


Felicidaesdes...

wellington1978
New Contributor III

Re: Dificuldades com Inner Join

Só uma dica:

Eu gosto de marcar as variáveis com os nomes dos meses e dias da semana com letras maiúsculas. Acho que fica mais bonito num painel.

SET MonthNames='JAN;FEV;MAR;ABR;MAI;JUN;JUL;AGO;SET;OUT;NOV;DEZ';

SET DayNames='SEG;TER;QUA;QUI;SEX;SAB;DOM';


Felicidades...

guilhermedorow
New Contributor II

Re: Dificuldades com Inner Join

De verdade, muito obrigado mesmo!