Skip to main content
Announcements
Have questions about Qlik Connect? Join us live on April 10th, at 11 AM ET: SIGN UP NOW
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

Percorrer registros e atualizar campos

Bom dia,

Preciso percorrer uma tabela com duas colunas (A e B), registro a registro.

AB
XM
X
X
Y
Y
Y
ZN
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:

AB
XM
XM
XM
YSUBY
YSUBY
YSUBY
ZN
ZN
ZN
ZN

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:

AB
XM
X
X

Depois:

AB
XM
XM
XM

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:

AB
Y
Y
Y

Depois:

AB
YSUBY
YSUBY
YSUBY

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.

1 Solution

Accepted Solutions
rphpacheco
Creator III
Creator III

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.

View solution in original post

8 Replies
eddysanchez
Partner - Creator
Partner - Creator

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;

eddysanchez
Partner - Creator
Partner - Creator

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;

Not applicable
Author

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:

AB
XM
X
X
Y
Y
Y
ZN
Z
ZO
Z

O grupo Z pode, da coluna A, pode ter mais de um campo preenchido. No caso deveria ficar assim:

AB
XM
XM
XM
YSUBY
YSUBY
YSUBY
ZN
ZN
ZO
ZO

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.

Not applicable
Author

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;

Not applicable
Author

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.

aderlanrm
Partner - Specialist
Partner - Specialist

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))));

Aderlan Rodrigues
Analista, Arquiteto de Dados e Piloto Amador Drone FPV
 (41) 9 9917-0869  www.BIdeAZ.com.br  Youtube.com/bideaz  Instagram.com/bideaz.in

"Nada é tão inútil quanto fazer eficientemente o que não deveria ser feito." (Peter Drucker)
rphpacheco
Creator III
Creator III

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.

Not applicable
Author

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!