配對間隔和反覆載入
LOAD 或 SELECT 陳述式的 Intervalmatch 前置詞是用於將離散數值連結到一或多個數值間隔。這是非常強大的功能,例如可用於生產等環境中。
使用 IntervalMatch() 前置詞
最基本的間隔配對是當您在一個表格中擁有一系列數字或日期 (事件),在另一個表格中擁有一系列間隔。您的目標是連結兩個表格。一般而言,這是多對多關係,即一個間隔包含位於其中的多個日期,並且一個日期也同屬於多個間隔。為了解決這個問題,您需要在兩個原始表格之間建立橋接表格。有多種方法可執行此操作。
在 Qlik Sense 中解決此問題的最簡單方法是在 LOAD 或 SELECT 陳述式前面加上 IntervalMatch() 前置詞。LOAD/SELECT 陳述式只需包含兩個欄位,即定義間隔的 From 和 To 欄位。IntervalMatch() 前置詞將產生已載入間隔與之前載入的數字欄位之間的所有組合,指定為該前置詞的參數。
請執行下列動作:
- 建立新的應用程式並命名。
- 在資料載入編輯器中新增新的指令碼區段。
- 叫用區段 Events。
-
在右側功能表的 DataFiles 之下,按一下選取資料。
- 上傳然後選取 Events.txt。
- 在從以下項目選取資料視窗中,按一下插入指令碼。
- 上傳然後選取 Intervals.txt。
- 在從以下項目選取資料視窗中,按一下插入指令碼。
- 在指令碼中,將第一個表格命名為事件,然後將第二個表格命名為 Intervals。
- 在指令碼的結尾處新增 IntervalMatch 以建立第三個表格,該表格橋接最初的兩個表格:
- 您的指令碼應如下所示:
- 按一下載入資料。
- 開啟資料模型檢視器。資料模型應如下所示:
- 每個事件只包含一個記錄的 Events 表格。
- 每個間隔只包含一個記錄的 Intervals 表格。
- 每個事件和間隔組合只包含一個記錄、並且連結之前兩個表格的橋接表格。
BridgeTable:
IntervalMatch (EventDate)
LOAD distinct IntervalBegin, IntervalEnd
Resident Intervals;
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;
資料模型包含一個複合索引鍵 (IntervalBegin 和 IntervalEnd 欄位),該索引鍵會將自身顯示為 Qlik Sense 合成鍵。
基本表格包括:
請注意,如果間隔彼此重疊,一個事件可能同時屬於多個間隔。一個間隔顯然同時包括多個事件。
本資料模型是一個標準化的精簡模型,是您的最佳選擇。Events 表格和 Intervals 表格均保持不變,並包含記錄的原始數值。在這些表格中進行的所有 Qlik Sense 計算,例如 Count(EventID),將正常工作並正確評估。
使用 While 迴圈和反覆載入 IterNo()
您可使用 While 迴圈和 IterNo() 得到幾乎一樣的橋接表格,該表格在間隔的上下限之間建立可列舉數值。
在 LOAD 陳述式內的迴圈可使用 While 子句建立。例如︰
只要 While 子句中的運算式為 true,此 LOAD 陳述式將重複每個輸入記錄並反覆載入。IterNo() 函數在首次反覆中返回「1」,在第二次中返回「2」,以此類推。
您有間隔的主要索引鍵 IntervalID,因此在指令碼中唯一的不同就是橋接表格的建立方式:
請執行下列動作:
- 使用下列指令碼取代現有的 Bridgetable 陳述式:
- 按一下載入資料。
- 開啟資料模型檢視器。資料模型應如下所示:
- 將下列指令碼新增至指令碼結尾:
- 按一下載入資料。
- 開啟資料模型檢視器。資料模型應如下所示:
BridgeTable:
LOAD distinct * Where Exists(EventDate);
LOAD IntervalBegin + IterNo() - 1 as EventDate, IntervalID
Resident Intervals
While IntervalBegin + IterNo() - 1 <= IntervalEnd;
一般而言,採用三個表格的解決方案是最佳方案,因為它允許間隔與事件之間存在多對多關係。但是有一種常見的情況,您知道一個事件只能屬於一個單一間隔。在此情況下,橋接表格並非必要。IntervalID 可以直接儲存在事件表格中。要執行此操作,有多種方法,最有用的方法就是將 Bridgetable 聯結到 Events 表格中。
Join (Events)
LOAD EventDate, IntervalID
Resident BridgeTable;
Drop Table BridgeTable;
開放和封閉的間隔
間隔是開放還是封閉由結束點確定,具體要看結束點是否包括在間隔內。
- 如果結束點包括在間隔內,則為封閉間隔:
- 如果結束點不包括在間隔內,則為開放間隔:
- 如果只有一個結束點包括在間隔內,則為半開放間隔:
[a,b] = {x ∈ ℝ ∣ a ≤ x ≤ b}
]a,b[ = {x ∈ ℝ ∣ a < x < b}
[a,b[ = {x ∈ ℝ ∣ a ≤ x < b}
如果遇到間隔重疊且一個數字可以同時屬於多個間隔的情況,您通常需要使用封閉間隔。
但在某些情況下,您不想要重疊間隔,您想讓一個數字只屬於一個間隔。因此,如果一個點位於一個間隔的結尾處,同時也位於下一個間隔的開頭,您就會遇到問題。這樣的數值將同屬於兩個間隔。因此,您想要半開放間隔。
此問題的實際解決方法是從所有間隔的結束值中減去少量值,這樣便可以建立封閉但不重疊的間隔。如果您的數值是日期,最簡單的方法就是使用函數 DayEnd(),該函數會返回當日的最後一毫秒:
您也可以手動減去少量值。如果您這麼做了,請確保減去的數量不至於太少,因為運算會四捨五入至 52 個有效二進位數字 (14 個小數位數)。如果您使用的量太小,差別不會很明顯,您將用回原來的數值。