Saltar al contenido principal

Correspondencia de intervalos y carga iterativa

El prefijo Intervalmatch delante de una sentencia LOAD o SELECT se utiliza para enlazar valores numéricos discretos con uno o más intervalos numéricos. Es una utilidad muy potente que se puede utilizar, por ejemplo, en entornos de producción.

Uso del prefijo IntervalMatch()

La correspondencia de intervalos más básica es cuando tenemos una lista de números o fechas (eventos) en una tabla y una lista de intervalos en una segunda tabla. El objetivo es vincular las dos tablas. En general, es una relación de muchos a muchos, es decir, un intervalo puede tener muchas fechas que pertenecen al mismo y una fecha puede pertenecer a muchos intervalos. Para solucionar esto, debe crear una tabla puente entre las dos tablas originales. Hay varias formas de hacerlo.

La forma más sencilla de resolver este problema en Qlik Sense es usar el prefijo IntervalMatch() frente a una sentencia LOAD o SELECT. La sentencia LOAD/SELECT necesita contener dos campos únicamente, los campos “From” y “To” que definen los intervalos. El prefijo IntervalMatch() generará a continuación todas las combinaciones entre los intervalos cargados y un campo numérico previamente cargado, especificado como parámetro para el prefijo.

Haga lo siguiente:

  1. Cree una nueva app y asígnele un nombre.
  2. Agregue una nueva sección de script en el Editor de carga de datos.
  3. Llame a las secciones Events.
  4. En DataFiles en el menú a la derecha, haga clic en Seleccionar datos.

  5. Cargue y después seleccione Events.txt.
  6. En la ventana Seleccionar datos de, haga clic en Insertar script.
  7. Cargue y después seleccione Intervals.txt.
  8. En la ventana Seleccionar datos de, haga clic en Insertar script.
  9. En el script, denomine Eventos a la primera tabla y Intervals a la segunda tabla.
  10. Al final del script agregue un IntervalMatch para crear una tercera tabla que una las dos primeras tablas:
  11. BridgeTable: IntervalMatch (EventDate) LOAD distinct IntervalBegin, IntervalEnd Resident Intervals;
  12. Su script debería tener el aspecto siguiente:
  13. Eventos: LOAD EventID, EventDate, EventAttribute FROM [lib://DataFiles/Events.txt] (txt, utf8, embedded labels, delimiter is '\t', msq);   Intervals: LOAD IntervalID, IntervalAttribute, IntervalBegin, IntervalEnd FROM [lib://DataFiles/Intervals.txt] (txt, utf8, embedded labels, delimiter is '\t', msq);   BridgeTable: IntervalMatch (EventDate) LOAD distinct IntervalBegin, IntervalEnd Resident Intervals;

  14. Haga clic en Cargar datos.
  15. Abra el Visor del modelo de datos. El modelo de datos tendrá el siguiente aspecto:
  16. Modelo de datos:Las tablas Events, BridgeTable, Intervals y $Syn1
    Data model: Events, BridgeTable, Intervals, and $Syn1 tables.

    El modelo de datos contiene una clave compuesta (los campos IntervalBegin y IntervalEnd) que se manifestará como una clave sintética de Qlik Sense:

    Las tablas básicas son:

    • La tabla Events que contiene exactamente un registro por evento.
    • La tabla Intervals que contiene exactamente un registro por intervalo.
    • La tabla puente, que contiene exactamente un registro por combinación de evento e intervalo, y que vincula las dos tablas anteriores.

    Tenga en cuenta que un evento puede pertenecer a varios intervalos si estos se solapan. Y un intervalo, por supuesto, puede tener varios eventos que pertenecen a él.

    Este modelo de datos es óptimo, en el sentido de que está normalizado y es compacto. La tabla Events y la tabla Intervals se mantienen ambas sin cambios y contienen el número original de registros. Todos los cálculos de Qlik Sense que operen en estas tablas, por ejemplo, Count(EventID), funcionarán y se evaluarán de manera correcta.

Nota informativaSi desea más información sobre IntervalMatch(), vea este blog en Qlik Community: Usar IntervalMatch()

Usar un bucle a While y carga iterativa IterNo()

Puede lograr casi la misma tabla puente utilizando un bucle While y IterNo() que crea valores enumerables entre los límites inferior y superior del intervalo.

Se puede crear un bucle dentro de la sentencia LOAD usando la cláusula While. Por ejemplo:

LOAD Date, IterNo() as Iteration From … While IterNo() <= 4;

Dicha sentencia LOAD recorrerá en bucle cada registro de entrada y cargará este una y otra vez mientras la expresión de la cláusula While sea verdadera. La función IterNo() devuelve “1” en la primera iteración, “2” en la segunda y así sucesivamente.

Tiene una clave primaria para los intervalos, IntervalID, por lo que la única diferencia en el script será cómo se crea la tabla puente:

Haga lo siguiente:

  1. Reemplace las sentencias Bridgetable existentes por el siguiente script:
  2. BridgeTable: LOAD distinct * Where Exists(EventDate); LOAD IntervalBegin + IterNo() - 1 as EventDate, IntervalID Resident Intervals While IntervalBegin + IterNo() - 1 <= IntervalEnd;

  3. Haga clic en Cargar datos.
  4. Abra el Visor del modelo de datos. El modelo de datos tendrá el siguiente aspecto:
  5. Modelo de datos:Tablas Events, BridgeTable y Intervals
    Data model: Events, BridgeTable, and Intervals tables.

    Generalmente la solución con tres tablas es la mejor, porque permite muchas relaciones entre intervalos y eventos. Pero una situación muy común es que sepa que un evento solo puede pertenecer a un único intervalo. En tal caso, la tabla puente no es realmente necesaria: El IntervalID se puede almacenar directamente en la tabla de eventos. Hay varias formas de lograrlo, pero la más útil es unir Bridgetable con la tabla Events.

  6. Agregue el siguiente script a la parte final de su script:
  7. Join (Eventos) LOAD EventDate, IntervalID Resident BridgeTable; Drop Table BridgeTable;

  8. Haga clic en Cargar datos.
  9. Abra el Visor del modelo de datos. El modelo de datos tendrá el siguiente aspecto:
  10. Modelo de datos:Tablas Events y Intervals
    Data model: Events and Intervals tables.

Intervalos abiertos y cerrados

El hecho de estar abierto o cerrado un intervalo viene determinado por los extremos, según si están incluidos en el intervalo o no.

  • Si los extremos están incluidos, se trata de un intervalo cerrado:
  • [a,b] = {x ∈ ℝ ∣ a ≤ x ≤ b}

  • Si los extremos no están incluidos, se trata de un intervalo abierto:
  • ]a,b[ = {x ∈ ℝ ∣ a < x < b}

  • Si un extremo está incluido, se trata de un intervalo semiabierto:
  • [a,b[ = {x ∈ ℝ ∣ a ≤ x < b}

Si tiene un caso en el que los intervalos se solapan y un número puede pertenecer a más de un intervalo, normalmente necesitará usar intervalos cerrados.

No obstante, en algunos casos no querrá intervalos que se solapen, sino un número que pertenezca solo a un intervalo. Por lo tanto, será un problema si un punto es el extremo de un intervalo y, a la vez, el principio del siguiente. Un número con este valor se atribuirá a ambos intervalos. Por lo tanto, desea unos intervalos semiabiertos.

Una solución práctica es restar una cantidad muy pequeña del valor final de todos los intervalos, creando de esta forma intervalos cerrados pero que no se solapen. Si sus números son fechas, la forma más sencilla de hacerlo es utilizar la función DayEnd() que devuelve el último milisegundo del día:

Intervalos: LOAD…, DayEnd(IntervalEnd – 1) as IntervalEnd From Intervals;

También puede restar una pequeña cantidad de forma manual. Si lo hace, asegúrese de que la cantidad restada no sea demasiado pequeña, ya que la operación se redondeará en 52 dígitos binarios significativos (14 dígitos decimales). Si usa una cantidad demasiado pequeña, la diferencia no será significativa y volverá a usar el número original.