跳到主要內容

配對間隔和反覆載入

LOADSELECT 陳述式的 Intervalmatch 前置詞是用於將離散數值連結到一或多個數值間隔。這是非常強大的功能,例如可用於生產等環境中。

使用 IntervalMatch() 前置詞

最基本的間隔配對是當您在一個表格中擁有一系列數字或日期 (事件),在另一個表格中擁有一系列間隔。您的目標是連結兩個表格。一般而言,這是多對多關係,即一個間隔包含位於其中的多個日期,並且一個日期也同屬於多個間隔。為了解決這個問題,您需要在兩個原始表格之間建立橋接表格。有多種方法可執行此操作。

Qlik Sense 中解決此問題的最簡單方法是在 LOADSELECT 陳述式前面加上 IntervalMatch() 前置詞。LOAD/SELECT 陳述式只需包含兩個欄位,即定義間隔的 FromTo 欄位。IntervalMatch() 前置詞將產生已載入間隔與之前載入的數字欄位之間的所有組合,指定為該前置詞的參數。

請執行下列動作:

  1. 建立新的應用程式並命名。
  2. 資料載入編輯器中新增新的指令碼區段。
  3. 叫用區段 Events
  4. 在右側功能表的 DataFiles 之下,按一下選取資料

  5. 上傳然後選取 Events.txt
  6. 從以下項目選取資料視窗中,按一下插入指令碼
  7. 上傳然後選取 Intervals.txt
  8. 從以下項目選取資料視窗中,按一下插入指令碼
  9. 在指令碼中,將第一個表格命名為事件,然後將第二個表格命名為 Intervals
  10. 在指令碼的結尾處新增 IntervalMatch 以建立第三個表格,該表格橋接最初的兩個表格:
  11. BridgeTable: IntervalMatch (EventDate) LOAD distinct IntervalBegin, IntervalEnd Resident Intervals;
  12. 您的指令碼應如下所示:
  13. Events: 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. 按一下載入資料
  15. 開啟資料模型檢視器。資料模型應如下所示:
  16. 資料模型: EventsBridgeTableIntervals$Syn1 表格
    Data model: Events, BridgeTable, Intervals, and $Syn1 tables.

    資料模型包含一個複合索引鍵 (IntervalBeginIntervalEnd 欄位),該索引鍵會將自身顯示為 Qlik Sense 合成鍵。

    基本表格包括:

    • 每個事件只包含一個記錄的 Events 表格。
    • 每個間隔只包含一個記錄的 Intervals 表格。
    • 每個事件和間隔組合只包含一個記錄、並且連結之前兩個表格的橋接表格。

    請注意,如果間隔彼此重疊,一個事件可能同時屬於多個間隔。一個間隔顯然同時包括多個事件。

    本資料模型是一個標準化的精簡模型,是您的最佳選擇。Events 表格和 Intervals 表格均保持不變,並包含記錄的原始數值。在這些表格中進行的所有 Qlik Sense 計算,例如 Count(EventID),將正常工作並正確評估。

資訊備註若要進一步瞭解 IntervalMatch(),請在 Qlik Community 中參閱此篇部落格貼文:使用 IntervalMatch()

使用 While 迴圈和反覆載入 IterNo()

您可使用 While 迴圈和 IterNo() 得到幾乎一樣的橋接表格,該表格在間隔的上下限之間建立可列舉數值。

LOAD 陳述式內的迴圈可使用 While 子句建立。例如︰

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

只要 While 子句中的運算式為 true,此 LOAD 陳述式將重複每個輸入記錄並反覆載入。IterNo() 函數在首次反覆中返回「1」,在第二次中返回「2」,以此類推。

您有間隔的主要索引鍵 IntervalID,因此在指令碼中唯一的不同就是橋接表格的建立方式:

請執行下列動作:

  1. 使用下列指令碼取代現有的 Bridgetable 陳述式:
  2. BridgeTable: LOAD distinct * Where Exists(EventDate); LOAD IntervalBegin + IterNo() - 1 as EventDate, IntervalID Resident Intervals While IntervalBegin + IterNo() - 1 <= IntervalEnd;

  3. 按一下載入資料
  4. 開啟資料模型檢視器。資料模型應如下所示:
  5. 資料模型: EventsBridgeTableIntervals 表格
    Data model: Events, BridgeTable, and Intervals tables.

    一般而言,採用三個表格的解決方案是最佳方案,因為它允許間隔與事件之間存在多對多關係。但是有一種常見的情況,您知道一個事件只能屬於一個單一間隔。在此情況下,橋接表格並非必要。IntervalID 可以直接儲存在事件表格中。要執行此操作,有多種方法,最有用的方法就是將 Bridgetable 聯結到 Events 表格中。

  6. 將下列指令碼新增至指令碼結尾:
  7. Join (Events) LOAD EventDate, IntervalID Resident BridgeTable; Drop Table BridgeTable;

  8. 按一下載入資料
  9. 開啟資料模型檢視器。資料模型應如下所示:
  10. 資料模型: EventsIntervals 表格
    Data model: Events and Intervals tables.

開放和封閉的間隔

間隔是開放還是封閉由結束點確定,具體要看結束點是否包括在間隔內。

  • 如果結束點包括在間隔內,則為封閉間隔:
  • [a,b] = {x ∈ ℝ ∣ a ≤ x ≤ b}

  • 如果結束點不包括在間隔內,則為開放間隔:
  • ]a,b[ = {x ∈ ℝ ∣ a < x < b}

  • 如果只有一個結束點包括在間隔內,則為半開放間隔:
  • [a,b[ = {x ∈ ℝ ∣ a ≤ x < b}

如果遇到間隔重疊且一個數字可以同時屬於多個間隔的情況,您通常需要使用封閉間隔。

但在某些情況下,您不想要重疊間隔,您想讓一個數字只屬於一個間隔。因此,如果一個點位於一個間隔的結尾處,同時也位於下一個間隔的開頭,您就會遇到問題。這樣的數值將同屬於兩個間隔。因此,您想要半開放間隔。

此問題的實際解決方法是從所有間隔的結束值中減去少量值,這樣便可以建立封閉但不重疊的間隔。如果您的數值是日期,最簡單的方法就是使用函數 DayEnd(),該函數會返回當日的最後一毫秒:

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

您也可以手動減去少量值。如果您這麼做了,請確保減去的數量不至於太少,因為運算會四捨五入至 52 個有效二進位數字 (14 個小數位數)。如果您使用的量太小,差別不會很明顯,您將用回原來的數值。