Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Earn the coveted Fabric Analytics Engineer certification. 100% off your exam for a limited time only!

Reply
DouweMeer
Post Prodigy
Post Prodigy

Generar tabla sobre disponibilidad

Tenía curiosidad de si se puede hacer lo siguiente en DAX.

Tengo estos productos con una gama.

IdEmpezarFinal
A15
B1

2

Y quería cambiar esta tabla de tal manera que generara un registro por paso del rango.

IdNivel
A1
A2
A3
A4
A5
B1
B2

¿Se puede hacer esto dinámicamente? Al igual que cuando el comienzo es 2, comienza en la segunda tabla de 2 también.

1 ACCEPTED SOLUTION
OwenAuger
Super User
Super User

@DouweMeer

Ciertamente puede hacerlo en DAX, o en Power Query para el caso.

En DAX, el código se vería algo como esto:

ModifiedTable = 
SELECTCOLUMNS ( 
    GENERATE ( 
        YourTable,
        GENERATESERIES ( YourTable[Start], YourTable[End] )
    ),
    "Id", YourTable[Id],
    "Level", [Value]
)

Alternativamente, en Power Query haría algo similar, agregando una columna que contiene una lista de números .[Inicio]. [Finalizar] y expandiendo eso a filas.

saludos

Owen


Owen Auger
Did I answer your question? Mark my post as a solution!
Blog
Twitter
LinkedIn

View solution in original post

10 REPLIES 10
v-alq-msft
Community Support
Community Support

Hola, @DouweMeer

Según su descripción, creé datos para reproducir su escenario. El archivo pbix se adjunta al final.

Mesa:

e1.png

Para no modificar los datos sin procesar, puede ir a 'Editor de consultas', duplicar 'Tabla', pegar los siguientes códigos m en 'Advanced Editor'.

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WclTSUTIEYlOlWJ1oJScoz0gpNhYA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Id = _t, Start = _t, End = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Id", type text}, {"Start", Int64.Type}, {"End", Int64.Type}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "Level", each let s=[Start],e=[End] in
List.Generate(
    ()=>s,
    each _<e+1,
    each _+1
)),
    #"Expanded Custom" = Table.ExpandListColumn(#"Added Custom", "Level"),
    #"Removed Columns" = Table.RemoveColumns(#"Expanded Custom",{"Start", "End"})
in
    #"Removed Columns"

Resultado:

e2.png

Saludos

Allan

Si este post ayuda,entonces considere Aceptarlo como la solución para ayudar a los otros miembros a encontrarlo más rápidamente.

@v-alq-msft

Su solución está en M, la solicité en DAX. Si me encuentras una solución en DAX... sólo entonces usted puede aceptar su comentario como una solución.

OwenAuger
Super User
Super User

@DouweMeer

Ciertamente puede hacerlo en DAX, o en Power Query para el caso.

En DAX, el código se vería algo como esto:

ModifiedTable = 
SELECTCOLUMNS ( 
    GENERATE ( 
        YourTable,
        GENERATESERIES ( YourTable[Start], YourTable[End] )
    ),
    "Id", YourTable[Id],
    "Level", [Value]
)

Alternativamente, en Power Query haría algo similar, agregando una columna que contiene una lista de números .[Inicio]. [Finalizar] y expandiendo eso a filas.

saludos

Owen


Owen Auger
Did I answer your question? Mark my post as a solution!
Blog
Twitter
LinkedIn

@OwenAuger

Gracias por la respuesta. Lo he probado, pero estoy luchando con el contexto de las generateseries, ya que espera un valor escalar y en su contexto implícito no hay ninguna referencia a un valor específico del registro. Así que espero que lo siguiente tenga en cuenta los valores específicos de nivel de registro.

así que... eso es como 7 millones de registros vs aproximadamente 365 registros en generateseries... Volveré mañana para ver si los resultados son satisfactorios.

Untitled.png

@DouweMeer sólo en el código DAX que publicó: Creo que la línea 7 debe ser cambiado a

GENERATESERIES ( [Inicio], [Fin], 1 )

Esto se debe a que GENERATE recorre en iteración las filas del 1er argumento (t1 en su caso) y evalúa la expresión de tabla en el 2o argumento en ese contexto de fila, por lo que [Start] y [End] hacen referencia a los valores de las filas specifix de t1. Usando MINX y MAXX de la manera que usted tiene daría valores máximos y mínimos generales que no es lo que desea.


Owen Auger
Did I answer your question? Mark my post as a solution!
Blog
Twitter
LinkedIn

@OwenAuger

Parece que tengo que corregirme en el error de argumento "en blanco". Parece, inexplicablemente, que mi conjunto de datos contiene espacios en blanco en la posición de inicio o fin. Lo estoy intentando de nuevo. Parece tener más dificultades con la expresión esta vez...

HI de nuevo @DouweMeer

Eso es bueno saber que hay algunos valores de inicio/ fin en blanco - entonces es un caso de manejarlos adecuadamente 🙂

También en el código que publicó justo antes de que parecía que había STRUCT_LI_ID en lugar de inicio del producto - es posible que ya lo haya corregido.

En cualquier caso, podría probar el código siguiente para eliminar los valores de inicio/fin en blanco y ver si eso al menos produce un resultado.

Si es necesario, puede ajustar esto para reemplazar Inicio/Fin en blanco con un valor adecuado.

Contract line Date Table =
VAR t1 =
    CALCULATETABLE (
        SELECTCOLUMNS (
            'Model N - Contract Line',
            "Line Id", 'Model N - Contract Line'[STRUCT_LI_ID],
            "Start", 'Model N - Contract Line'[Product Start],
            "End", 'Model N - Contract Line'[Product End]
        ),
        // Eliminate blank Start/End for now
        NOT ISBLANK ( 'Model N - Contract Line'[Product Start] ),
        NOT ISBLANK ( 'Model N - Contract Line'[Product End] )
    )
RETURN
    SELECTCOLUMNS (
        GENERATE ( t1, GENERATESERIES ( [Start], [End], 1 ) ),
        "Line Id", [Line Id],
        "Level", [Value]
    )

saludos

Owen


Owen Auger
Did I answer your question? Mark my post as a solution!
Blog
Twitter
LinkedIn

Eso es simplemente increíble....

Tuve que crear una tabla independiente, ya que se agotó de mi memoria de 32 GB después de ejecutar la expresión con bastante rapidez :).

Untitled2.png

Untitled.png

Una cosa...

éste...:

    CALCULATETABLE (
        SELECTCOLUMNS (
            'Model N - Contract Line',
            "Line Id", 'Model N - Contract Line'[STRUCT_LI_ID],
            "Start", 'Model N - Contract Line'[Product Start],
            "End", 'Model N - Contract Line'[Product End]
        ),
        // Eliminate blank Start/End for now
        NOT ISBLANK ( 'Model N - Contract Line'[Product Start] ),
        NOT ISBLANK ( 'Model N - Contract Line'[Product End] )
    )

Se puede escribir como tal (¿o hay una ventaja de rendimiento que no agrega el filtro en el contexto de tabla de las columnas selectas?):

SELECTCOLUMNS (
	Filter ( 'Model N - Contract Line',
		NOT ISBLANK ( 'Model N - Contract Line'[Product Start] ),
		NOT ISBLANK ( 'Model N - Contract Line'[Product End] )	
		)
	"Line Id", 'Model N - Contract Line'[STRUCT_LI_ID],
	"Start", 'Model N - Contract Line'[Product Start],
	"End", 'Model N - Contract Line'[Product End]
	)

A propósito...

¿Por qué la gente se siente como poner la coma al final de la línea más bien en frente? ¿Alguna razón particular para esto que no sepa?

Me alegro de que la lógica DAX funcione, incluso si puede que no funcione lo suficientemente bien en el conjunto de datos completo. Tal vez esta tabla podría construirse con Power Query o más ascendente.

Sobre la cuestión de si utilizar FILTER o CALCULATETABLE:

Por lo general, es mejor aplicar FILTER a tablas de tan pequeña cardinalidad como sea posible. FILTER recorre en iteración fila la tabla proporcionada y evalúa el 2o argumento para cada fila.

Así que esta expresión podría ser bastante costosa, ya que recorre en iteración todas las filas de 'Modelo N - Línea de contrato':

FILTER( 'Model N - Contract Line', ... )

En la versión CALCULATETABLE, las dos expresiones

NOT ISBLANK ( 'Model N - Contract Line'[Product Start] ),
NOT ISBLANK ( 'Model N - Contract Line'[Product End] )

en realidad se convierten a

FILTER (
    ALL ( 'Model N - Contract Line'[Product Start] ),
    NOT ISBLANK ( 'Model N - Contract Line'[Product Start] )
),
FILTER (
    ALL ( 'Model N - Contract Line'[Product End] ),
    NOT ISBLANK ( 'Model N - Contract Line'[Product End] )
)

lo que da como resultado dos iteraciones: sobre todos los valores de Inicio del producto y todos los valores de Product End, que supongo que podrían ser un número total menor de iteraciones que toda la tabla.

En este artículo se trata bien el tema:

https://www.sqlbi.com/articles/filter-vs-calculatetable-optimization-using-cardinality-estimation/

En cuanto a las comas iniciales o finales, sé que muchos siguen las convenciones de DAX Formatter con comas finales. Sin embargo, ciertamente conozco a algunas personas que prefieren comas principales también. Supongo que se reduce a la preferencia.

saludos

Owen


Owen Auger
Did I answer your question? Mark my post as a solution!
Blog
Twitter
LinkedIn

@OwenAuger Por lo que veo es que cuando me levanto a la parte de generación...

Contract line Date Table = 
VAR t1 = SELECTCOLUMNS( 'Model N - Contract Line' , "Line Id" , 'Model N - Contract Line'[STRUCT_LI_ID] , "Start" , 'Model N - Contract Line'[STRUCT_LI_ID] , "End" , 'Model N - Contract Line'[Product End] )
RETURN
SELECTCOLUMNS(
     GENERATE(
          t1 
         , GENERATESERIES( [

en este contexto, no se puede 'encontrar ningún valor de campo". El valor esperado por él es escalar en lugar de una columna.

Untitled2.png

Como puede ver, el [Inicio] y [Fin] no se recoge ya que el contexto de nivel de fila no se reconoce en esta parte de la expresión.

Continuando con la expresión...

Contract line Date Table = 
VAR t1 = SELECTCOLUMNS( 'Model N - Contract Line' , "Line Id" , 'Model N - Contract Line'[STRUCT_LI_ID] , "Start" , 'Model N - Contract Line'[STRUCT_LI_ID] , "End" , 'Model N - Contract Line'[Product End] )
RETURN
SELECTCOLUMNS(
     GENERATE(
          t1 
         , GENERATESERIES( [Start] , [End] , 1 )
         )
     , "Line Id" , [Line Id]
     , "Level" , [Value]
     )

Devolverá el error 'Los argumentos de GenerateSeries no pueden estar en blanco'. De alguna manera hay que especificar que tiene que tomar el valor del contexto de registro de la primera tabla en generar. Con la expresión actual no parece posible.

Helpful resources

Announcements
April AMA free

Microsoft Fabric AMA Livestream

Join us Tuesday, April 09, 9:00 – 10:00 AM PST for a live, expert-led Q&A session on all things Microsoft Fabric!

March Fabric Community Update

Fabric Community Update - March 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors