Query “invisível”

No Power Query, a transformação de dados muitos vezes passa por criar um variado número de passos que permitem chegar ao resultado esperado. No entanto muitas vezes verificamos que temos demasiados passos ou a criação de queries auxiliares.

No processo de ETL (extract, transform and load), muitas vezes é ignorado o fato de que podemos usar queries dentro de outras queries, e também dentro do cálculo de uma coluna, e com a invocação de diversas funções agregadamente atingir o resultado esperado.

O processo de “aninhar” queries é uma das grandes vantagens da linguagem M, assim com o fato de que muitas vezes a combinação de diversas funções.

Vamos então ver um exemplo como podemos criar uma query dentro de uma coluna.

Exemplo

Objetivo: Adicionar uma coluna com o valor multiplicado pelo máximo de cada categoria

Dados: Duas colunas – Cat Value

Resultado pretendido:

Vamos apresentar as duas soluções e como podemos então reduzir o número de passos “visíveis” no nosso ETL.

Todos os passos

De modo a conseguirmos a transformação podemos realizar os seguintes passos:

  • Agrupar por Cat e Máximo do Valor
  • Fazer um merge da query com ela própria pela Cat
  • Alterar o passo para ir buscar o passo do Changed Type em vez do agrupamento
Previous:
= Table.NestedJoin(#"Grouped Rows", {"Cat"}, #"Grouped Rows", {"Cat"}, "Grouped Rows", JoinKind.LeftOuter)

Change to
= Table.NestedJoin(#"Changed Type", {"Cat"}, #"Grouped Rows", {"Cat"}, "Grouped Rows", JoinKind.LeftOuter)
  • Expandir a coluna MaximumValue da coluna Grouped Rows
  • Adicionar uma coluna personalizada com o código:
[Value] * [MaximumValue]
  • Eliminar a coluna Maximum Value

Como podemos verificar criamos 6 passos para fazer todas as transformações, o nosso exemplo não é muito grande e não tem grande complexidade nos passos, no entanto temos aqui dois passos que são recorrentes dentro da query (Grouped Rows e Merged Queries)

Vamos então tentar apresentar uma solução com um único passo

Um único passo

  • Table.Group: cria uma tabela agrupada por categoria sendo o mesmo código utilizado na opção anterior podemos verificar pela seleção de uma das células da nossa tabela:
Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}})

Se verificarmos este código é o primeiro passo da opção anterior em que agrupamos por categoria isto pode ser verificado selecionando uma das células da nossa tabela.

Vamos agora proceder a alteração da nossa coluna acrescentando funções

  • Table.SelectRows: permite-nos filtrar a tabela para cada categoria correspondente de modo que cada célula nos devolve um único resultado:

  Table.SelectRows (
    Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}}), 
    (x) =>
      x[Cat] = [Cat]
      )

Ao adicionarmos a sintaxe (x) => usamos a tabela anterior como uma variável que nos vai permitir chamar a coluna da Cat e comparar com a linha Cat da nossa tabela assim temos uma única linha por registo.

  • Table.SelectColumns: Seleção da coluna que queremos para o nosso cálculo neste caso o valor máximo:
Table.SelectColumns( 
  Table.SelectRows (
    Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}}), 
    (x) =>
      x[Cat] = [Cat]
      ), "ValueMaximum")
  • {0}[Value Maximum]: sintaxe para obter o valor de um registo dentro de uma célula especifica
Table.SelectColumns( 
  Table.SelectRows (
    Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}}), 
    (x) =>
      x[Cat] = [Cat]
      ), "ValueMaximum"){0}[Value Maximum]
  • Multiplicação pelo Valor:
Table.SelectColumns( 
  Table.SelectRows (
    Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}}), 
    (x) =>
      x[Cat] = [Cat]
      ), "ValueMaximum"){0} [ValueMaximum] * [Value]

Como podemos verificar o resultado é o mesmo do anterior, no entanto temos apenas 3 passos:

Tal como referi anteriormente este exemplo não apresenta grande complexidade, no entanto demonstra flexibilidade da linguagem M e a forma como podemos combinar diferentes opções para o nosso processo de ETL ser enriquecido.

No entanto é importante referir que esta abordagem apresenta desvantagens nomeadamente no que concerne ao debug do código. Tendo um passo único, com o resultado poderá não ser simples encontrar os erros devido a não visibilidade sobre os resultados intermédios

Código:

Todos os passos:
let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WSlTSUTI0UIrVgTJN4UxjiGgSkGmKYBoimEYQZjKQaYZgmiCYUAUpQKYFgmmJYIIMiwUA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Cat = _t, Value = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Value", Int64.Type}}),
    #"Grouped Rows" = Table.Group(#"Changed Type", {"Cat"}, {{"MaximumValue", each List.Max([Value]), type nullable number}}),
    #"Merged Queries" = Table.NestedJoin(#"Changed Type", {"Cat"}, #"Grouped Rows", {"Cat"}, "Grouped Rows", JoinKind.LeftOuter),
    #"Expanded Grouped Rows" = Table.ExpandTableColumn(#"Merged Queries", "Grouped Rows", {"MaximumValue"}, {"MaximumValue"}),
    #"Added Custom" = Table.AddColumn(#"Expanded Grouped Rows", "Value * Maximum", each [Value] * [MaximumValue]),
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"MaximumValue"})
in
    #"Removed Columns"
Passo único:
let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WSlTSUTI0UIrVgTJN4UxjiGgSkGmKYBoimEYQZjKQaYZgmiCYUAUpQKYFgmmJYIIMiwUA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Cat = _t, Value = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Value", Int64.Type}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Value * Maximum per Category", each Table.SelectColumns( 
  Table.SelectRows (
    Table.Group(#"Changed Type", {"Cat"},
     {{"ValueMaximum", each List.Max([Value]), 
     type nullable number}}), 
    (x) =>
      x[Cat] = [Cat]
      ), "ValueMaximum"){0} [ValueMaximum] * [Value])
in
    #"Added Custom"

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão /  Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão /  Alterar )

Connecting to %s

%d bloggers gostam disto: