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

Earn a 50% discount on the DP-600 certification exam by completing the Fabric 30 Days to Learn It challenge.

Reply
Syndicate_Admin
Administrator
Administrator

CALCULAR + USORELACIÓN: La evaluación se comporta de manera diferente cuando se divide en medidas

Hola a todos

hoy tengo una pregunta muy teórica para usted, que apunta principalmente a obtener una mejor comprensión de cómo se comporta exactamente DAX en este escenario y por qué lo hace.

Dado:

  • Tengo una tabla de hechos que contiene información de ventas
  • Hay dos columnas de fecha diferentes en la tabla de ventas, llamémoslas fecha de pedido y fecha de factura
  • Tengo una tabla de dimensiones de fecha con mi jerarquía de fechas principal
  • Hay una relación activa de la tabla de fechas a la columna de fecha de pedido de mi tabla de hechos
  • Hay una relación inactiva de la tabla de fechas a la columna de fecha de factura de mi tabla de hechos
  • Quiero crear una matriz visual con las siguientes proyecciones:
    • Filas: Algunos campos de categoría, como grupo de productos, fabricante, etc.
    • Columnas: Años de mi tabla de fechas
    • Valores: Una medida específica que cuenta los elementos en la tabla de ventas
  • El principal problema es que en esta matriz quiero usar el año de la fecha de la factura como columnas, que no tiene una relación activa con la tabla de fechas, esto no se supone que deba cambiarse ya que la relación de fecha de pedido debe seguir siendo la conexión principal.

La medida de la que estoy hablando se parece a esto:

Measure = 
CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    FILTER( Sales, Sales[Product Group] = "abc" ),
    FILTER( Sales, Sales[Price] > 500 ),
    ...
)

La expresión también podría ser una suma o cualquier otra agregación.

Entonces, pensé que sabía muy bien cómo resolver fácilmente este problema agregando la función USERELATIONSHIP como un argumento de filtro de mi función CALCULATE dentro de la medida. Sin embargo, algo como esto no funcionará:

Measure = 
CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    FILTER( Sales, Sales[Product Group] = "abc" ),
    FILTER( Sales, Sales[Price] > 500 ),
    ...
    USERELATIONSHIP( Sales[Invoice Date], Date[Date] )
)

Los valores de mi matriz todavía están separados en las columnas del año por la fecha del pedido.

A continuación, traté de externalizar el cálculo de la medida en una variable. Pero como antes, este tampoco funcionará:

Measure = 
VAR calc =
    CALCULATE(
        DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
        FILTER( Sales, Sales[Product Group] = "abc" ),
        FILTER( Sales, Sales[Price] > 500 ),
        ...
    )
RETURN
    CALCULATE(
        calc,
        USERELATIONSHIP( Sales[Invoice Date], Date[Date] )
    )

Lo último que he intentado fue la clave del éxito. En lugar de evaluar el cálculo solo una vez dentro de una sola medida, creé una segunda medida adicional a la medida base (que es la del primer bloque de código). La segunda medida simplemente se refiere a la medida base y aplica el comportamiento de relación diferente:

Measure = 
CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    FILTER( Sales, Sales[Product Group] = "abc" ),
    FILTER( Sales, Sales[Price] > 500 ),
    ...
)
Measure_2 = 
CALCULATE(
    [Measure],
    USERELATIONSHIP( Sales[Invoice Date], Date[Date] )
)

Ahora sé cómo manejar tales casos, todo funciona bien para mí. Pero este problema todavía me desencadena, porque estoy perdiendo el punto, cuál es exactamente la razón de este comportamiento. Personalmente, como modelador, preferiría tener solo una medida, ya que solo hay una salida que voy a usar para mi modelo de datos. La medida base no se utilizará en ningún otro lugar. Es solo un cálculo previo.

Espero que alguien pueda explicar los antecedentes de este comportamiento y tal vez incluso proporcionar una solución en la que pueda combinar los pasos de evaluación en una sola medida.

¡Muchas gracias si has leído hasta aquí!

Saludos desde Alemania

6 REPLIES 6
Syndicate_Admin
Administrator
Administrator

Gracias @PabloDeheza !

Aunque no pude implementar su solución correctamente en mi modelo, su idea me llevó a una que funciona para mí.

En lugar de dos opciones que se eligen en función de una condición IF, creé dos tablas con las diferentes configuraciones de filtro en dos variables y las fusioné. Después de eso, la medida cuenta las filas distintas, lo que genera exactamente el número que quería.

Aquí está mi solución:

VAR _Intercompany = 
    CALCULATETABLE(
        DISTINCT( Sales[Item ID] ),
        .
        .    // common filters
        .
        Kunden[Gruppe] = "Intercompany",
        Sales[Mandant] = "50",
        USERELATIONSHIP( Sales[Rechnungsdatum], Date[Date] )
    )

VAR _NotIntercompany = 
    CALCULATETABLE(
        DISTINCT( Sales[Item ID] ),
        .
        .    // common filters
        .
        Kunden[Gruppe] <> "Intercompany", 
        USERELATIONSHIP( Sales[Rechnungsdatum], Date[Date] )
    )

VAR _combine =
    DISTINCT( 
        UNION( _Intercompany , _NotIntercompany )
    )

RETURN
    COUNTROWS( _combine )

¡Muchas gracias por tu ayuda!

Syndicate_Admin
Administrator
Administrator

La única idea que me viene a la mente en este momento es usar una declaración IF, donde:

VAR _Intercompany = 
    CALCULATE(
        DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
        Sales[Vertriebsart] = "Handel" ,
        Sales[Typ] = "N" ,
        Produktgruppe[Key] = "M",
        Sales[Mandant] = "50",
        Sales[Rechnungsnummer] <> BLANK() ,
        'AP'[P_Text]  <> "Dublette" 
    )
VAR _NotIntercompany = 
    CALCULATE(
        DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
        Sales[Vertriebsart] = "Handel" ,
        Sales[Typ] = "N" ,
        Produktgruppe[Key] = "M",
        Kunden[Gruppe] <> "Intercompany", 
        Kunden[Gruppe] = "Intercompany" && Sales[Mandant] = "50"
        ),
        Sales[Rechnungsnummer] <> BLANK(),
        'AP'[P_Text]  <> "Dublette" 
    )
RETURN
    IF(
        Kunden[Gruppe] = "Intercompany",
        _Intercompany,
        _NotIntercompany
    )

Syndicate_Admin
Administrator
Administrator

Muchas gracias @PabloDeheza !

Esto es en realidad algo de lo que no era consciente.

Ya casi llegamos, todavía queda un problema con la siguiente parte:

Kunden[Gruppe] = "Intercompany" && Sales[Mandant] = "50"

No puedo usar dos campos de dos tablas diferentes para una operación lógica sin FILTER & RELATED. O al menos no sé cómo hacerlo.

Cuando uso AND en lugar de && también arroja un error.

Syndicate_Admin
Administrator
Administrator

Si esos filtros relacionados provienen de otras dimensiones y la relación entre Ventas y la Dimensión es Muchos (Ventas) a Una (Dimensión), entonces no debería necesitar RELACIONADO. Como mencionas, RELATED necesita un contexto de fila, pero simplemente podrías aplicar un filtro en la dimensión, algo como esto:

CALCULATE(
    DISTINCTCOUNTNOBLANK( InternetSales[ProductKey] ),
    InternetSales[StoreKey] = 306 ,
    InternetSales[Net Price] > 8 ,
    'Product'[Brand] = "Contoso",
    OR(
        'Product'[Color] = "Blue",
        'Product'[Color] = "Red"
    ),
    USERELATIONSHIP( InternetSales[Delivery Date], TablaFecha[Fecha] )
)

En su caso si no me equivoco sería:

CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    Sales[Vertriebsart] = "Handel" ,
    Sales[Typ] = "N" ,
    Produktgruppe[Key] = "M",
    OR( 
        Kunden[Gruppe] <> "Intercompany", 
        Kunden[Gruppe] = "Intercompany" && Sales[Mandant] = "50"
    ),
    Sales[Rechnungsnummer] <> BLANK() ,
    'AP'[P_Text]  <> "Dublette" 
)

Una vez más, esto funcionará si se siguen las mejores prácticas de modelado de datos, es decir, principalmente la implementación de un esquema en estrella.
https://www.sqlbi.com/articles/power-bi-star-schema-or-single-table/

Syndicate_Admin
Administrator
Administrator

Muchas gracias por tu respuesta súper rápida @PabloDeheza, ¡se lo agradezco!

Tienes un punto allí, las declaraciones FILTER no son necesarias en mi ejemplo.

El problema es que mi medida real es un poco más compleja, solo traté de mantenerla simple para la explicación.

Mi medida se ve más o menos así:

CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    FILTER( Sales, Sales[Vertriebsart] = "Handel" ),
    FILTER( Sales, Sales[Typ] = "N" ),
    FILTER( Sales, RELATED( Produktgruppe[Key] ) = "M",
    FILTER( Sales, 
        OR( 
            RELATED ( Kunden[Gruppe] ) <> "Intercompany", 
            RELATED ( Kunden[Gruppe] ) = "Intercompany" && Sales[Mandant] = "50"
        )
    ),
    FILTER( Sales, Sales[Rechnungsnummer] <> BLANK() ),
    FILTER( Sales, RELATED( 'AP'[P_Text] ) <> "Dublette" )
)

Como puede ver, hay muchos filtros que provienen de otras tablas de dimensiones a través de RELATED.

No puedo usar esos filtros sin una función FILTER, porque RELATED necesita el contexto de fila.

Así que esta es la razón por la que envolví cada argumento dentro de una declaración FILTER.
Podría eliminarlo para los filtros en la tabla de hechos, pero no para los que provienen de una tabla relacionada.

Syndicate_Admin
Administrator
Administrator

Hola @timalbers !
Creo que las funciones FILTER están estropeando su código. Usted debe intentar:

Measure = 
CALCULATE(
    DISTINCTCOUNTNOBLANK( Sales[Item ID] ),
    Sales[Product Group] = "abc" ,
    Sales[Price] > 500 ,
    ...
    USERELATIONSHIP( Sales[Invoice Date], Date[Date] )
)

FILTRO dentro de CALCULAR son la mayoría de las veces no necesarios. Teóricamente calcular aplica un FILTRO por defecto, por lo que

CALCULATE (
    ,
    table[column] =  
)

se transforma internamente en

CALCULATE (
    ,
    FILTER (
        ALL ( table[column] ),
        table[column] =  
    )
)

Aquí hay alguna documentación sobre el tema que lo explicará mejor que yo:
https://www.sqlbi.com/articles/filter-arguments-in-calculate/

https://www.sqlbi.com/articles/specifying-multiple-filter-conditions-in-calculate/

¡Espero que esto ayude!

Helpful resources

Announcements
PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

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