(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo calcular tiempo medio de resolución en DAX: paso a paso

João Barros 11 de August de 2026 4 min de lectura

Este tutorial muestra cómo calcular el tiempo medio de resolución (en horas o días) de tickets en DAX —útil para evaluar SLA y rendimiento de soporte. Vamos a explicar por qué usar medidas en lugar de columnas calculadas y dar un ejemplo práctico con variables, tratamiento de valores faltantes y sugerencias para validar los resultados en el modelo.

Requisitos previos

  • Power BI Desktop u otro cliente que soporte DAX.
  • Modelo con una tabla de hechos llamada Tickets que contenga las columnas code TicketID, code CreatedDate, code ResolvedDate y code Status.
  • Tabla de fechas Date con la columna code Date marcada como Date Table. Tener una Date Table permite filtrar por mes, trimestre y calcular correctamente totales acumulados.
  • Volumen de datos ejemplificativo: si tiene 10 000 tickets, las medidas abajo serán rápidas; en 1 000 000 de filas conviene probar rendimiento y usar agregaciones.

Paso 1: Entender por qué usar medida y no columna

Una columna calculada genera un valor por fila en el momento de la actualización y aumenta el tamaño del modelo. Por ejemplo, una columna adicional con un número que ocupa 8 a 16 bytes por fila en una tabla de 1 000 000 de filas puede consumir 8 a 16 MB adicionales, y más en metadatos. Además, una columna es estática y no reacciona al contexto de filtro en un visual.

Una medida calcula dinámicamente en el contexto visual. Para tiempo medio de resolución queremos flexibilidad: filtrar por periodo, equipo, prioridad o estado y ver cómo cambia la media. Por eso usamos medidas —menos almacenamiento y más flexibilidad.

Paso 2: Calcular la diferencia de tiempo básica (horas)

Vamos a crear una medida que calcule la diferencia entre ResolvedDate y CreatedDate en horas. La función DATEDIFF devuelve un entero cuando usamos HOUR, por lo que la media será en horas enteras. Para obtener decimales podemos usar DATEDIFF en minutes y dividir por 60.

Explicación del código: filtramos Tickets para excluir filas con fechas faltantes o mal formadas, y garantizamos que ResolvedDate sea mayor o igual a CreatedDate. Luego usamos AVERAGEX sobre ese conjunto.

Avg Resolution Hours =
VAR ResolvedTickets =
    FILTER(
        Tickets,
        NOT(ISBLANK(Tickets[ResolvedDate]))
            && NOT(ISBLANK(Tickets[CreatedDate]))
            && Tickets[ResolvedDate] >= Tickets[CreatedDate]
    )
RETURN
    AVERAGEX(
        ResolvedTickets,
        DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], HOUR)
    )

Si quiere precisión decimal a nivel de minutos, use:

Avg Resolution Hours Precise =
VAR Resolved =
    FILTER(
        Tickets,
        NOT(ISBLANK(Tickets[ResolvedDate]))
            && NOT(ISBLANK(Tickets[CreatedDate]))
            && Tickets[ResolvedDate] >= Tickets[CreatedDate]
    )
RETURN
    AVERAGEX(Resolved, DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], MINUTE) / 60)

Ejemplo numérico: en un conjunto de 10 000 tickets resueltos, si la suma de las diferencias en horas es 52 000, la media será 5,2 horas por ticket.

Paso 3: Tratar outliers y valores extremos

Los outliers pueden distorsionar la media. Por ejemplo, si el 1% de los tickets tardó 365 días en resolverse, la media sube mucho. Un enfoque simple es excluir duraciones por encima de un límite razonable, por ejemplo 90 días. En 10 000 tickets, 90 días = 2160 horas; si 200 tickets exceden ese límite, estamos excluyendo el 2% de los casos.

Avg Resolution Hours (Trimmed) =
VAR MaxHours = 90 * 24
VAR ResolvedTickets =
    FILTER(
        Tickets,
        NOT(ISBLANK(Tickets[ResolvedDate]))
            && NOT(ISBLANK(Tickets[CreatedDate]))
            && Tickets[ResolvedDate] >= Tickets[CreatedDate]
            && DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], HOUR) <= MaxHours
    )
RETURN
    IF(
        COUNTROWS(ResolvedTickets)=0,
        BLANK(),
        AVERAGEX(ResolvedTickets, DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], HOUR))
    )

Alternativas: usar medianas para una medida robusta o calcular percentiles como el percentil 90 para comprender la distribución. Verifique siempre cuántas filas fueron excluidas con una medida de conteo para confirmar que el corte no elimina demasiados datos legítimos.

Paso 4: Media ponderada por prioridad (opcional)

Si desea dar más peso a tickets de alta prioridad, use una media ponderada. Asumimos una columna Priority con valores numéricos 1 a 5. Esto tiene sentido si, por ejemplo, un ticket Priority 5 es tres veces más crítico que Priority 1.

Weighted Avg Resolution Hours =
VAR Resolved =
    FILTER(
        Tickets,
        NOT(ISBLANK(Tickets[ResolvedDate]))
            && NOT(ISBLANK(Tickets[CreatedDate]))
            && Tickets[ResolvedDate] >= Tickets[CreatedDate]
    )
VAR SumWeighted =
    SUMX(
        Resolved,
        DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], HOUR) * COALESCE(Tickets[Priority],1)
    )
VAR SumWeights =
    SUMX(Resolved, COALESCE(Tickets[Priority],1))
RETURN
    DIVIDE(SumWeighted, SumWeights)

Si Priority es texto (High, Medium, Low), conviértalo antes con SWITCH o cree una columna de mapeo.

Paso 5: Mostrar en días y formatear para el usuario

Para mostrar el resultado en días con un decimal convierta horas a días. En Power BI, defina el formato de la medida para Mostrar como Número con 1 decimal.

Avg Resolution Days =
VAR Hours = [Avg Resolution Hours]
RETURN
    IF(ISBLANK(Hours), BLANK(), Hours / 24)

Si prefiere hh:mm muestre horas enteras y minutos con INT y MOD o use FORMAT para formatear como cadena pero evite FORMAT en indicadores que se van a usar en cálculos.

Verificar el resultado

Creé una visualización de tarjeta o tabla con las medidas: code Avg Resolution Hours, code Avg Resolution Hours (Trimmed) y code Avg Resolution Days. Filtre por mes o equipo para confirmar que los valores cambian según lo esperado. Compare con una tabla de muestra de 50 tickets: calcule manualmente algunos ejemplos para validar la media.

Medidas útiles para validación:

Resolved Count =
CALCULATE(COUNTROWS(Tickets), NOT(ISBLANK(Tickets[ResolvedDate])))

Trimmed Count =
CALCULATE(
    COUNTROWS(Tickets),
    NOT(ISBLANK(Tickets[ResolvedDate])),
    DATEDIFF(Tickets[CreatedDate], Tickets[ResolvedDate], HOUR) <= 90*24
)

Verifique que Resolved Count y Trimmed Count tengan sentido y que el número excluido sea plausible (por ejemplo 1-5% dependiendo del histórico).

Conclusión

Ahora sabe calcular el tiempo medio de resolución en DAX, tratar outliers y aplicar ponderación por prioridad. Próximos pasos recomendados: calcular percentiles (p.ej. 90th percentile) para comprender la cola de la distribución, crear una medida para el porcentaje de tickets dentro del SLA y asegurar que las fechas estén en una zona horaria consistente antes de calcular duraciones. Consejo de rendimiento: use variables, evite iteradores innecesarios en tablas grandes y pre-agregue cuando sea posible para modelos con millones de filas.