Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
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
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...
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.......
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..
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...
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:
É Correto trabalhar dessa forma ou você recomendaria manter apenas os campos chaves e relacionar esses campos com as outras tabelas?
De verdade, muito obrigado!!
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...
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...
De verdade, muito obrigado mesmo!