メイン コンテンツをスキップする

間隔の一致と反復ロード

Intervalmatch プレフィックスを LOAD または SELECT ステートメントで使用すると、不連続の数値が 1 つ以上の数値間隔にリンクされます。これはとても有用な機能で、実稼働環境などで使用できます。

IntervalMatch() プレフィックスの使用

もっとも基本的な間隔一致は、1 つのテーブルに数値や日付 (イベント) のリストが存在し、2 つ目のテーブルに間隔のリストがある場合です。目的は、この 2 つのテーブルをリンクさせることです。一般的に、これは多対多の関係です。つまり、間隔には多数の日付が属し、日付は多数の間隔に属する場合があります。これを解決するには、2 つのオリジナル テーブル間の橋渡しとなるブリッジ テーブルを作成する必要があります。これには、さまざまな方法があります。

Qlik Sense におけるこの問題を解決するもっとも簡単は方法は、IntervalMatch() プレフィックスを LOAD または SELECT ステートメントの前に配置する方法です。LOAD/SELECT ステートメントには、間隔を定義する FromTo という 2 つの項目のみを含める必要があります。IntervalMatch() プレフィックスは、プレフィックスのパラメータで指定された、ロード済みの間隔と前にロードされた数値項目間のすべての組み合わせを生成します。

  1. 新しいアプリを作成し、名前を付けます。
  2. データ ロード エディターで新しいスクリプト セクションを追加します。
  3. このセクションを Events と呼びます。
  4. 右のメニューの [DataFiles] で、[データを選択] をクリックします。

  5. Events.txt をアップロードして選択します。
  6. [Select data from] (データの選択元) ウィンドウで、[スクリプトを挿入] をクリックします。
  7. Intervals.txt をアップロードして選択します。
  8. [Select data from] (データの選択元) ウィンドウで、[スクリプトを挿入] をクリックします。
  9. スクリプトで、1 つ目のテーブルに Events、2 つ目のテーブルに Intervals という名前を付けます。
  10. スクリプトの最後に IntervalMatch を追加して、最初の 2 つのテーブルをリンクさせる 3 つ目のテーブルを作成します。
  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 テーブル

    データ モデル:

    データ モデルには複合キー (IntervalBeginIntervalEnd 項目) が含まれ、これは Qlik Sense 合成キーとして現れます。

    基本的なテーブルは、

    • イベントごとに正確に 1 つのレコードを含む、Events テーブル。
    • 間隔ごとに正確に 1 つのレコードを含む、Intervals テーブル。
    • イベントと間隔の組み合わせごとに正確に 1 つのレコードを含み、上記 2 つのテーブルをリンクさせているブリッジ テーブル。

    間隔の重複によって、イベントに複数の間隔が付属している場合があります。そして 1 つの間隔に複数のイベントが付属している場合もあります。

    このデータ モデルは、データの正規化やコンパクト化という意味においては最適です。Events テーブルと Intervals テーブルは、ともに不変で元の数と同じレコード数が含まれています。Count(EventID) など、これらのテーブルで行われる Qlik Sense のすべての計算は、正しく動作し、評価されます。

情報メモIntervalMatch() について詳しくは、Qlik Community の次のブログ投稿を参照してください。IntervalMatch() の使用

While ループの使用と IterNo() の反復ロード

間隔の下限と上限間の可算値を生成する While ループと IterNo() を使用すると、ブリッジ テーブルと同様の結果が得られます。

LOAD ステートメント内のループは、次のように While 節を使って作成できます。例:

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

このような LOAD ステートメントは、各入力レコードを何度もループし、While 節の数式が true である限りロードは何度も続きます。IterNo() 関数は、最初の反復では「1」、2 回目の反復では「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. データ モデル: EventsBridgeTable、および Intervals テーブル

    データ モデル:

    一般に、3 つのテーブルを有するソリューションが最善です。これは間隔とイベント間に多対多の関係が許容されるからです。ですが多くの場合、1 つのイベントには単一の間隔が付属します。この場合、ブリッジ テーブルは必要ではありません。IntervalID は、イベント テーブルに直接保存されます。これを実現するにはいくつかの方法がありますが、もっとも有用な方法は BridgetableEvents テーブルを結合することです。

  6. 次のスクリプトを、スクリプトの最後に追加します。
  7. Join (Events) LOAD EventDate, IntervalID Resident BridgeTable;   Drop Table BridgeTable;

  8. [データのロード] をクリックします。
  9. [データ モデル ビューア] を開きます。データ モデルは次のようになります。
  10. データ モデル: Events および Intervals テーブル

    データ モデル:

開区間と閉区間

間隔が開いているまたは閉じているかどうかは、エンドポイントが間隔に含まれているかどうかで判断します。

  • エンドポイントが含まれている場合、それは閉区間です。
  • [a,b] = {x ∈ ℝ ∣ a ≤ x ≤ b}

  • エンドポイントが含まれていない場合、それは開区間です。
  • ]a,b[ = {x ∈ ℝ ∣ a < x < b}

  • 1 つのエンドポイントが含まれている場合、それは半開区間です。
  • [a,b[ = {x ∈ ℝ ∣ a ≤ x < b}

間隔が重複している場合や数値が 2 つ以上の間隔に付属している場合、通常は閉区間を使用する必要があります。

しかし、間隔を重複させずに、1 つの間隔にのみ数値を付属させたい場合もあります。よって、1 つのポイントが 1 つの間隔の終端にあり、同時に次の間隔の冒頭にある場合は問題になります。この値を持つ数値は、両方の間隔に属することになります。つまり、このような場合は半開区間を使用します。

この問題の現実的な解決策は、すべての間隔の終点地から少量を差し引き、閉じているが重複しない間隔を作成することです。数値が日付だった場合、日付の最後のミリ秒を返す DayEnd() 関数を使用するのが、もっとも簡単な方法です。

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

手動で少量を差し引くこともできます。これを実施すると、値が 2 進 52 桁の有効数字 (10 進 14 桁) に四捨五入されるため、差し引いた量が小さすぎないことを確認してください。小さすぎる値を使用すると、差異に意味がなくなり、元の数値が使用されます。