Error: Es posible que las mediciones con agregaciones de Looker (suma, promedio, mínimo, máximo, tipos de lista) no hagan referencia a otras mediciones

Mientras desarrollas en un proyecto, es posible que veas un error como el siguiente en un explorador o en el Validador de Looker:

  Measures with Looker aggregations (sum, average, min, max, list types) may not reference other measures.

Este error se produce por una medida agregada que hace referencia a otra agregación o medida de cualquier tipo en su definición de LookML, como la siguiente:

    SELECT AVG((COUNT(*)) ) AS users.average_count FROM demo_db.users  AS users

Las instrucciones de SQL como esta generan una agregación doble o anidada en SQL; la mayoría de los dialectos de SQL no pueden agregar doblemente ni anidar agregaciones, por lo que un intento de este tipo activa el error.

Soluciones

Hay dos soluciones posibles:

  1. Usa medidas no agregadas para realizar instrucciones de SQL no agregadas entre mediciones.
  2. Usar una tabla derivada para anidar agregaciones o agregar dobles

Usa medidas no agregadas

Las medidas no agregadas, como type: yesno y type: number, son las únicas medidas que pueden hacer referencia a otras medidas o agregaciones. Las medidas no agregadas no realizan ninguna agregación y, por lo tanto, no realizarán una agregación doble o anidada. Las mediciones de type: number o type: yesno actúan como marcadores de posición para que se pueda hacer referencia a otras mediciones o combinaciones de medidas dentro de ellas.

Por ejemplo, las medidas de type: number se usan para realizar cálculos entre medidas y tomar cualquier expresión de SQL válida que dé como resultado un número o un número entero.

En el siguiente ejemplo, se usa un type: number para calcular el porcentaje de todos los pedidos que se cancelan:

measure: order_count { # Base measure #1
    type: count
    sql: ${order_id} ;;
}

measure: cancelled_orders { # Base measure #2
    type: count
    filters: [status: "Cancelled"]
}

measure: percent_cancelled_orders { # New measure
    type: number
    sql: (1.0*${cancelled_orders})/ISNULL(${order_count},0) ;;
}

Usa una tabla derivada para agregaciones dobles o anidadas

Pero ¿qué pasa si es necesaria una agregación anidada para realizar un análisis? Por ejemplo, ¿qué sucede si necesitas conocer el importe promedio que invierten los clientes a lo largo del ciclo de vida del cliente ("valor promedio del ciclo de vida del cliente")? Esto requiere dos niveles de agregaciones, de duplicación o anidación, que incluyen lo siguiente:

  1. Una suma de las ventas agrupadas por cliente

  2. Un promedio de esa suma

Para lograrlo con LookML, puedes intentar lo siguiente:

measure: total_revenue {
    type: sum
    sql: ${sale_price} ;;
}

measure: avg_customer_lifetime_value {
    type: average
    sql: ${total_revenue} ;;
}

Sin embargo, esto activará el error porque la medida avg_customer_lifetime_value realiza una agregación en la medición total_revenue, que ya es una agregación. Como se explicó anteriormente, la mayoría de los dialectos de SQL activarán un error cuando se utilicen agregados dobles o anidados en una consulta.

Para lograr un promedio de la suma total_revenue en SQL, se necesita una subconsulta como la siguiente:

  SELECT AVG(s.sum) FROM (SELECT SUM(x) as sum FROM ...) AS s

La solución equivalente en Looker es crear una tabla derivada para "compactar" la medición total_lifetime_value en un campo que se pueda agregar. En Looker, esto se denomina dimensionamiento de una medida. Con una tabla derivada, la medida total_lifetime_value se convierte en una dimensión. Luego, puedes crear una medición de type: average que haga referencia a la dimensión customer_lifetime_value:

view: customer_facts {
    derived_table: {
        sql:
        SELECT
            user_id,
            COALESCE(SUM(sale_price), 0) AS customer_lifetime_value
        FROM orders
        GROUP BY user_id;;
    }

    dimension: customer_lifetime_value {
        type: number
        sql: ${TABLE}."customer_lifetime_value" ;;
    }

    measure: average_customer_lifetime_value {
        type: average
        sql: ${customer_lifetime_value} ;;
    }
}

Una vez que la tabla derivada customer_facts se une a una exploración, se puede usar la medición average_customer_lifetime_value para realizar el análisis deseado en una exploración sin activar ningún error.