Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Bom dia,
Preciso percorrer uma tabela com duas colunas (A e B), registro a registro.
A | B |
---|---|
X | M |
X | |
X | |
Y | |
Y | |
Y | |
Z | N |
Z | |
Z | |
Z |
A coluna A é completamente preenchida, e a B possui alguns campos vazios. O valor da coluna A se repete em grupos (x,y,z).
Preciso fazer a trasnformação a seguir:
A | B |
---|---|
X | M |
X | M |
X | M |
Y | SUBY |
Y | SUBY |
Y | SUBY |
Z | N |
Z | N |
Z | N |
Z | N |
Ou seja, em um grupo de valores da coluna A, por exemplo X (3 primeiros registros), SE existir um valor no primeiro registro da coluna B referênte ao grupo de valores da coluna A, os campos vazios de B, referentes a esse grupo da coluna A, devem receber o valor desse primeiro registro, no caso, o M.
Antes:
A | B |
---|---|
X | M |
X | |
X |
Depois:
A | B |
---|---|
X | M |
X | M |
X | M |
Caso contrário, se esse primero registro da coluna B, referênte a um grupo de valores da coluna A (no caso Y), for vazio, os campos desse grupo de valores na coluna B devem ser preenchidos com uma string "SUB"+ Valor do campo da coluna A.
Antes:
A | B |
---|---|
Y | |
Y | |
Y |
Depois:
A | B |
---|---|
Y | SUBY |
Y | SUBY |
Y | SUBY |
Preciso percorrer cada registro, olhando o registro anterior e o atual, e gerando os valores desses campos novos.
Como eu poderia fazer isso no QlikView?
Aguardo ajuda,
Atenciosamente,
Thiago.
Bom dia Tiago.
Criei um QVW exemplo e um arquivo em Excel que faz isso.
Você poderá colocar este código na leitura do xls que anexei:
[Tabela A e B]:
LOAD
A,
B, // Você terá que carregar esta coluna para que a função Peek funcione
If(RecNo() = 1, B, // Aqui você verificará se contém dado no primeiro
If(A = Peek(A, -1), // Aqui ele verifica se o registro da coluna A é igual ao registro anterior da mesma coluna
If(IsNull(B), // Se forem iguais ele verificará se B é nulo
Peek(BB), B // Se for, ele irá pegar o último registro, senão apenas B
)
,If(IsNull(B), 'SUB'&A, // Se A for diferente de seu registro anterior e b for nulo ele trará 'SUB'+(Valor de A)
B // Senão B
)
)
)
as BB
FROM
Pasta1.xlsx
(ooxml, embedded labels, table is Plan1);
Bom, considerei que o primeiro registro seja um valor como vc colocou no exemplo, mas se caso ele possa ser nulo é só você colocar mais uma condicional para tratar isso
Espero que tenha ajudado!
Abs.
Tabela:
LOAD * INLINE [
A,B
X,M
X,
X,
Y,
Y,
Y,
Z,N
Z,
Z,
Z,
];
Grupo:
LOAD A,
FirstValue(B) as PrimeiroB
Resident Tabela
Group By A;
DROP Field B;
Left Join (Tabela)
LOAD A,
If(PrimeiroB='','SUBY',PrimeiroB) as B
Resident Grupo;
DROP Table Grupo;
Ou melhor ainda assim:
Tabela:
LOAD * INLINE [
A,B
X,M
X,
X,
Y,
Y,
Y,
Z,N
Z,
Z,
Z,
];
Left Join (Tabela)
LOAD A,
If(FirstValue(B)='','SUBY',FirstValue(B)) as BCompleto
Resident Tabela
Group By A
Order By A,B desc;
DROP Field B;
RENAME Field BCompleto to B;
A solução realmente ficou ótima e funcionaria no cenário acima.
O problema é que essa solução no meu cenário não funciona, eu precisa mesmo varrer a tabela, pelo seguinte, esse é um possível cenário também:
A | B |
---|---|
X | M |
X | |
X | |
Y | |
Y | |
Y | |
Z | N |
Z | |
Z | O |
Z |
O grupo Z pode, da coluna A, pode ter mais de um campo preenchido. No caso deveria ficar assim:
A | B |
---|---|
X | M |
X | M |
X | M |
Y | SUBY |
Y | SUBY |
Y | SUBY |
Z | N |
Z | N |
Z | O |
Z | O |
A regra no geral é:
Na coluna B, preencher o campo vazio com o valor preenchido acima (dentro do mesmo grupo da coluna A), se não houver valor preenchido dentro do grupo da coluna A, preencher com a string "SUB" + Valor da coluna A.
Olá, veja se ajuda. Coloquei uma "indexação".
Abs
Tabela:
LOAD * INLINE [
0,A,B
1,X,M
2,X,
3,X,
4,Y,
5,Y,
6,Y,
7,Z,N
8,Z,
9,Z,
10,Z,
];
Left Join (Tabela)
LOAD A,
If(FirstValue(B)='','SUB'& A, FirstValue(B)) as BCompleto
Resident Tabela
Group By A
Order By A,B desc
;
DROP Field B;
RENAME Field BCompleto to B;
Rodolfo,
A indexação não vai alterar o problema, pois o:
LOAD A,
If(FirstValue(B)='','SUB'& A, FirstValue(B)) as BCompleto
Resident Tabela
Group By A
Order By A,B desc
cria uma tabela um para um para o join, onde para cada A existe um B.
Boa noite pessoal,
Existe um recurso de transformação de dados na hora da carga, lá quando escolhemos arquivos de tabela para ser carregado, isso pode ser usado em conjunto.
Coloquei comentários no código, abraço.
Temp:
// Segundo LOAD, aqui fazemos o tratamento dos grupos
LOAD A,
// cuidado com o B = '', dependendo da origem use IsNull(B)
if(A <> Previous(A) and B = '','SUB'&A,B) as B;
// Primeiro LOAD, aqui você substitui pela origem
LOAD *
INLINE [
A, B
X, M
X,
X,
Y,
Y,
Y,
Z, N
Z,
Z, O
Z,
];
// Armazena o resultado tratado para usar o recurso de filtros durante a carga
STORE Temp into etl.qvd (qvd);
// Apaga pois vamos recaregar já certinho
DROP Table Temp;
Final:
// Terceiro LOAD, observe o FILTERS, ele preenche os campos vazios com o valor da celula superior
LOAD @1 as A,
@2 as B
FROM etl.qvd
(qvd, filters(Replace(2, top, StrCnd(null))));
Bom dia Tiago.
Criei um QVW exemplo e um arquivo em Excel que faz isso.
Você poderá colocar este código na leitura do xls que anexei:
[Tabela A e B]:
LOAD
A,
B, // Você terá que carregar esta coluna para que a função Peek funcione
If(RecNo() = 1, B, // Aqui você verificará se contém dado no primeiro
If(A = Peek(A, -1), // Aqui ele verifica se o registro da coluna A é igual ao registro anterior da mesma coluna
If(IsNull(B), // Se forem iguais ele verificará se B é nulo
Peek(BB), B // Se for, ele irá pegar o último registro, senão apenas B
)
,If(IsNull(B), 'SUB'&A, // Se A for diferente de seu registro anterior e b for nulo ele trará 'SUB'+(Valor de A)
B // Senão B
)
)
)
as BB
FROM
Pasta1.xlsx
(ooxml, embedded labels, table is Plan1);
Bom, considerei que o primeiro registro seja um valor como vc colocou no exemplo, mas se caso ele possa ser nulo é só você colocar mais uma condicional para tratar isso
Espero que tenha ajudado!
Abs.
Bom dia Raphael!
Ontem no meio da madrugadona eu consegui resolver! hehe
...mas valeu mesmo pela resposta, ótima solução.
Para quem interessar a minha solução ficou menos bonita, mas fiz assim:
Criei um WHILE de 1 até o total de registros.
Dentro do WHILE usei o "LET variavel = Peek('CAMPO',$(i),'TABELA');
Assim eu varria a tabela conforme o 'i' ia incrementando pelo $(i).
Criei 4 variáveis(a, aAnt, b, bAtn) para receber do PEEK, duas para o campo A (registro anterior e o atual) e duas para o campo B (registro anterior e atual).
Tendo os 4 valores, foi só uma questão de lógica com IF's para repreencher o valor das 4 variáveis.
Depois só dava um load dentro do WHILE:
TABELA:
LOAD * INLINE
[A, B
$(a),$(b)];
Que o auto concatenate do Qlikview montava a tabela com os valores das variáveis, que eram atualizadas com o PEEK e os IF's em cada LOOP.
Obrigado a todo mundo!