jueves, 22 de julio de 2021

Power Query: Cruce con coincidencia parcial

Os propongo hoy un ejercicio interesante donde cruzar o combinar dos tablas de acuerdo a una coincidencia parcial entre campos de dichas tablas.

Power Query: Cruce con Coincidencia Parcial

Se trata en definiva de recuperar la cuenta contable asociada a cada 'Descripción', según los 'Conceptos' definidos.
El handicap está en que las Descripciones y los Conceptos no son iguales, y solo coinciden parcialmente!!.

Conseguiremos esto empleando funciones M como:
Text.Contains(text as nullable text, substring as text, optional comparer as nullable function) as nullable logical
esta función devolverá TRUE o FALSE si detecta que el primer argumento 'text' contiene el segundo argumento 'substring'.
Interesante el argumento opcional 'comparer' que nos da tres opciones:
-Comparer.Ordinal: se usa para realizar una comparación ordinal exacta.
-Comparer.OrdinalIgnoreCase: se usa para realizar una comparación ordinal exacta que no distingue mayúsculas de minúsculas.
-Comparer.FromCulture: para una comparación compatible con referencias culturales.

Otra función que emplearemos será:
Table.SelectRows(table as table, condition as function) as table
la cual nos devuelve una tabla con las filas de la 'table' que coincidan con la selección dada en el argumento 'condition'.

Además haremos uso de la función Table.Buffer, de la que puedes leer algo más aquí.

Comenzaremos cargando solo como conexión nuestras dos tablas...

A continuación accederemos al editor de Power Query creando una consulta en blanco (que llamaremos 'TblCRUCE_CoincidenciaParcial') donde escribiremos la siguiente consulta:
let
//cargamos la tabla con los movimientos contables
Origen = TblMAYOR,
//cargamos en memoria la tabla de cuentas
//ya que vamos a llamarla recurrentemente una vez por cada fila de la tabla MAYOR
Buffer_TblCUENTAS = Table.Buffer(TblCUENTAS),

//añadimos una columna con el dato de 'cuenta contable' que cruce..
CoincidenciaParcial=
        Table.AddColumn(Origen, "Cuenta",
                        //declaramos una variable que nos permita ir fila por fila en la tabla MAYOR
                        (RecorreCadaFiladeMAYOR)=>
                        //y seleccionaremos la fila o filas de la tabla CUENTAS cargada en memoria
                        Table.SelectRows(Buffer_TblCUENTAS,
                                        //cuando después de recorrer cada fila de CUENTAS
                                        (RecorreCadaFilaCUENTA)=>
                                        //encuentre que en la Descripción existe el Concepto
                                        //sin hacer distinciones entre mayúsculas y minúsculas
                                        Text.Contains(RecorreCadaFiladeMAYOR[Descripción],
                                                      RecorreCadaFilaCUENTA[Concepto],
                                                      Comparer.OrdinalIgnoreCase))[Cuenta contable]{0})
in
    CoincidenciaParcial

Power Query: Cruce con Coincidencia Parcial


Date cuenta que Table.SelectRows en realidad nos devuelve una tabla!!, por lo que habitualmente bastaría con expandir las columnas.. pero en este caso es más simple recuperar el campo [Cuenta contable] y de la lista obtenida, al tener a priori bastante claro que solo debería haber una única coincidencia, recuperamos el primer dato de esa lista (usando {0}).

Especialmente interesante en este ejemplo propuesto es el uso de Table.Buffer para agilizar la busqueda una y otra vez sobre la tabla de CUENTAS...
Si no la usaramos para cada fila tendría que cargar una y otra vez todos los datos de CUENTAS, con el consiguiente retardo en la ejecución de nuestra query...

Por otra parte, también interesante, es el uso de variables para concretar los argumentos iterativos de Table.AddColumn y Table.SelectRows.
Como habíamos mencionado previamente Table.SelectRows devuelve una tabla con las filas de la 'table' que coincidan con la selección dada en el argumento 'condition'; por lo que obviamente debe recorrer fila por fila para detectar si dicha fila cumple o no la condición...
y Table.AddColumn incorpora una nueva columna a nuestra tabla. Sabiendo que los valores de la columna se calculan usando la función de selección especificada en la que cada fila se toma como una entrada (i.e., recorre fila por fila para realizar el cálculo y obtener el resultado!!).

Esto podría ser equivalente, hasta cierto punto, con lo expuesto en las entradas del blog sobre funciones recursivas, por ejemplo lo explicado en este artículo.

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.