間隔の一致と反復ロード
Intervalmatch プレフィックスを LOAD または SELECT ステートメントで使用すると、不連続の数値が 1 つ以上の数値間隔にリンクされます。これはとても有用な機能で、実稼働環境などで使用できます。
IntervalMatch() プレフィックスの使用
もっとも基本的な間隔一致は、1 つのテーブルに数値や日付 (イベント) のリストが存在し、2 つ目のテーブルに間隔のリストがある場合です。目的は、この 2 つのテーブルをリンクさせることです。一般的に、これは多対多の関係です。つまり、間隔には多数の日付が属し、日付は多数の間隔に属する場合があります。これを解決するには、2 つのオリジナル テーブル間の橋渡しとなるブリッジ テーブルを作成する必要があります。これには、さまざまな方法があります。
Qlik Sense におけるこの問題を解決するもっとも簡単は方法は、IntervalMatch() プレフィックスを LOAD または SELECT ステートメントの前に配置する方法です。LOAD/SELECT ステートメントには、間隔を定義する From と To という 2 つの項目のみを含める必要があります。IntervalMatch() プレフィックスは、プレフィックスのパラメータで指定された、ロード済みの間隔と前にロードされた数値項目間のすべての組み合わせを生成します。
次の手順を実行します。
- 新しいアプリを作成し、名前を付けます。
- データ ロード エディターで新しいスクリプト セクションを追加します。
- このセクションを Events と呼びます。
-
右のメニューの [DataFiles] で、[データを選択] をクリックします。
- Events.txt をアップロードして選択します。
- [Select data from] (データの選択元) ウィンドウで、[スクリプトを挿入] をクリックします。
- Intervals.txt をアップロードして選択します。
- [Select data from] (データの選択元) ウィンドウで、[スクリプトを挿入] をクリックします。
- スクリプトで、1 つ目のテーブルに Events、2 つ目のテーブルに Intervals という名前を付けます。
- スクリプトの最後に IntervalMatch を追加して、最初の 2 つのテーブルをリンクさせる 3 つ目のテーブルを作成します。
- これで、スクリプトは次のようになります。
- [データのロード] をクリックします。
- [データ モデル ビューア] を開きます。データ モデルは次のようになります。
- イベントごとに正確に 1 つのレコードを含む、Events テーブル。
- 間隔ごとに正確に 1 つのレコードを含む、Intervals テーブル。
- イベントと間隔の組み合わせごとに正確に 1 つのレコードを含み、上記 2 つのテーブルをリンクさせているブリッジ テーブル。
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 合成キーとして現れます。
基本的なテーブルは、
間隔の重複によって、イベントに複数の間隔が付属している場合があります。そして 1 つの間隔に複数のイベントが付属している場合もあります。
このデータ モデルは、データの正規化やコンパクト化という意味においては最適です。Events テーブルと Intervals テーブルは、ともに不変で元の数と同じレコード数が含まれています。Count(EventID) など、これらのテーブルで行われる Qlik Sense のすべての計算は、正しく動作し、評価されます。
While ループの使用と IterNo() の反復ロード
間隔の下限と上限間の可算値を生成する While ループと IterNo() を使用すると、ブリッジ テーブルと同様の結果が得られます。
LOAD ステートメント内のループは、次のように While 節を使って作成できます。例:
このような LOAD ステートメントは、各入力レコードを何度もループし、While 節の数式が true である限りロードは何度も続きます。IterNo() 関数は、最初の反復では「1」、2 回目の反復では「2」というように値を返します。
間隔には IntervalID というプライマリ キーがあるため、スクリプトにおける唯一の違いはブリッジ テーブルを作成する方法です。
次の手順を実行します。
- 既存の Bridgetable ステートメントを、次のスクリプトと置き換えます。
- [データのロード] をクリックします。
- [データ モデル ビューア] を開きます。データ モデルは次のようになります。
- 次のスクリプトを、スクリプトの最後に追加します。
- [データのロード] をクリックします。
- [データ モデル ビューア] を開きます。データ モデルは次のようになります。
BridgeTable:
LOAD distinct * Where Exists(EventDate);
LOAD IntervalBegin + IterNo() - 1 as EventDate, IntervalID
Resident Intervals
While IntervalBegin + IterNo() - 1 <= IntervalEnd;
一般に、3 つのテーブルを有するソリューションが最善です。これは間隔とイベント間に多対多の関係が許容されるからです。ですが多くの場合、1 つのイベントには単一の間隔が付属します。この場合、ブリッジ テーブルは必要ではありません。IntervalID は、イベント テーブルに直接保存されます。これを実現するにはいくつかの方法がありますが、もっとも有用な方法は Bridgetable と Events テーブルを結合することです。
Join (Events)
LOAD EventDate, IntervalID
Resident BridgeTable;
Drop Table BridgeTable;
開区間と閉区間
間隔が開いているまたは閉じているかどうかは、エンドポイントが間隔に含まれているかどうかで判断します。
- エンドポイントが含まれている場合、それは閉区間です。
- エンドポイントが含まれていない場合、それは開区間です。
- 1 つのエンドポイントが含まれている場合、それは半開区間です。
[a,b] = {x ∈ ℝ ∣ a ≤ x ≤ b}
]a,b[ = {x ∈ ℝ ∣ a < x < b}
[a,b[ = {x ∈ ℝ ∣ a ≤ x < b}
間隔が重複している場合や数値が 2 つ以上の間隔に付属している場合、通常は閉区間を使用する必要があります。
しかし、間隔を重複させずに、1 つの間隔にのみ数値を付属させたい場合もあります。よって、1 つのポイントが 1 つの間隔の終端にあり、同時に次の間隔の冒頭にある場合は問題になります。この値を持つ数値は、両方の間隔に属することになります。つまり、このような場合は半開区間を使用します。
この問題の現実的な解決策は、すべての間隔の終点地から少量を差し引き、閉じているが重複しない間隔を作成することです。数値が日付だった場合、日付の最後のミリ秒を返す DayEnd() 関数を使用するのが、もっとも簡単な方法です。
手動で少量を差し引くこともできます。これを実施すると、値が 2 進 52 桁の有効数字 (10 進 14 桁) に四捨五入されるため、差し引いた量が小さすぎないことを確認してください。小さすぎる値を使用すると、差異に意味がなくなり、元の数値が使用されます。