La función GENERATE devuelve una tabla formada por el producto cartesiano de todas las filas de la primera tabla y las filas de la segunda tabla tras ser evaluadas en el contexto de fila de cada una de las filas de la primera. O, dicho con otras palabras, para cada una de las filas de la primera tabla se crea un contexto de fila que se aplica a la segunda tabla antes de realizar la combinación.
GENERATE(
table1,
table2
)
- table1: Primera tabla, cuyas filas van a generar el contexto de fila.
- table2: Segunda tabla, cuyas filas se van a contextualizar antes de realizar el producto cartesiano.
La función GENERATE devuelve una tabla resultado de realizar el producto cartesiano entre las filas de la primera tabla y las filas de la segunda tabla tras ser contextualizadas.
Las tablas deberán tener columnas con nombres no coincidentes pues, en otro caso, la función GENERATE devolverá un error.
En este primer ejemplo partimos de las siguientes dos tablas:
Obsérvese que estas tablas tienen un campo en común ("Oficina"), por lo que la creación de una tabla calculada usando la función GENERATE va a devolver un error:
Curiosamente, sí es posible usar esta función para generar una tabla intermedia sobre la que aplicar otras funciones:
Como, en este ejercicio, queremos visualizar la tabla resultante de aplicar la función GENERATE a nuestras dos tablas de datos, vamos a generar una nueva tabla, Tabla2B, con los mismos campos que la Tabla2 pero cambiando el nombre del campo "Oficina", cosa que haremos utilizando la función SELECTCOLUMNS:
Tabla2B =
SELECTCOLUMNS(
Tabla2;
"Oficina2", Tabla2[Oficina];
"Compras", Tabla2[Compras]
)
Ahora ya podríamos aplicar la función GENERATE a las tablas Tabla1 y Tabla2B. Si lo hacemos sin más, el resultado es el mismo que tendríamos al utilizar la función CROSSJOIN:
En este caso, la aplicación del contexto de fila generado por cada una de las filas de la primera tabla no ha modificado el resultado del producto cartesiano.
Pero, si en lugar de aplicar la función GENERATE a la Tabla2B, lo hacemos al resultado de filtrar dicha tabla considerando los campos de Tabla1, el resultado es bien distinto. Realicemos dicho filtrado con la función FILTER:
Tabla =
GENERATE(
Tabla1,
FILTER(
Tabla2B,
Tabla1[Oficina] = Tabla2B[Oficina2]
)
)
Veamos qué ha ocurrido:
La función ha recorrido cada una de las filas de la primera tabla, creando un contexto de fila para cada una de ellas. Así, para la primera, el contexto de fila viene dado por, entre otras cosas, "Oficina" = "España". A continuación se ha aplicado este contexto de fila a la segunda tabla, que es el resultado de aplicar a Tabla2B un filtro según el cual el valor del campo Oficina2 debe coincidir con el resultado del campo Oficina de la primera tabla. Como resultado de aplicar este contexto de fila, la segunda tabla se ha visto reducida a aquellas filas en las que el campo Oficina2 tome el valor "España" (un único registro en este caso). A continuación, se ha multiplicado la fila siendo considerada de la primera tabla por todas y cada una de las filas de la segunda tabla tras la aplicación del contexto (una única fila). El resultado de este primer paso es -en este ejemplo- una única fila con los campos de ambas tablas para los registros en los que el nombre de la oficina sea "España".
Tras evaluar la primera fila de la primera tabla se realizaría el mismo procedimiento con todas y cada una de las demás filas de esta tabla, generándose un contexto de fila, aplicándose a la segunda tabla, y multiplicándose la fila de la primera tabla por las resultantes en la segunda tabla.
En este ejemplo en el que todos los valores de los campos relativos a las oficinas están presentes en ambas tablas, el resultado es semejante a una combinación interna.
Para probar esta última afirmación, repitamos la operación incluyendo una oficina en la primera tabla que no exista en la segunda, y una en la segunda que no exista en la primera:
Apliquemos ahora la función GENERATE con el filtro visto:
Efectivamente, cuando para una fila de la primera tabla no hay al menos otra equivalente en la segunda, el producto es un conjunto vacío (y no se devuelve resultado). Y lo mismo ocurre cuando una fila de la segunda tabla nunca llega a ser multiplicada por ninguna de la primera al no tener un equivalente.
Por supuesto, no estamos obligados a trabajar con una única condición. Supongamos que partimos de las siguientes tablas:
Tras cambiar el nombre del campo "Oficina" de la segunda podríamos aplicar la función GENERATE de la siguiente forma:
Tabla =
GENERATE(
Tabla1;
FILTER(
Tabla2B;
Tabla1[Oficina] = Tabla2B[Oficina2] &&
Tabla1[Año] <= 2018
)
)
En este caso estamos creando un contexto de fila que incluye el nombre de la oficina de la fila siendo considerada en la primera tabla y que el año para dicha fila sea inferior o igual a 2018. Si el resultado de aplicar este contexto de fila a la segunda tabla es una tabla vacía, no se generará ninguna fila en la tabla resultante de aplicar la función GENERATE.