5

私は2つの異なる方法で解決した状況にありますが、人々がオプションについてどう考えているか、他の選択肢があるかどうか疑問に思っていました...

システムはデータの「間隔」を処理しています。

  • すべてのデータは「間隔」に割り当てられます
  • 間隔は、ファクト テーブルの "interval_start" DATETIME で表されます。
  • ディメンション テーブルには、「間隔」の期間が保持されます (エンティティごとに異なる場合があります)。
  • また、ディメンション テーブルには「モード」フラグがあります。


SQL クエリには次のルールが必要です...

モード 0
レコード エントリがファクト テーブルにある場合は、処理できます。
(制限はありません。)

モード 1
"interval_start" が過去の場合、レコードは処理に対してのみ有効です。(すでに開始されているが、必ずしも終了しているとは限らない時間間隔。)

モード 2
レコードは、「間隔」全体が過去にある場合にのみ処理に有効です。(終了した時間間隔。)


このために作成された最初の WHERE 句は次のとおりです...

WHERE
    getDate() >=
        CASE [table].mode
            WHEN 0 THEN 0
            WHEN 1 THEN [log].interval_start
            WHEN 2 THEN [log].interval_start + [table].interval_period
            ELSE        NULL
        END


これにより、インデックスが節を最適化するのがわかりにくくなるという懸念がありました。別の方法は、複数の AND/OR 条件を使用することでした。

WHERE
   ([table].mode = 0 AND getDate() >= 0)
OR ([table].mode = 1 AND getDate() >= [log].interval_start)
OR ([table].mode = 2 AND getDate() >= [log].interval_start + [table].interval_period)


明らかに、どれが最も効果的かは、データやインデックスなどによって異なります。しかし、私が現在「条件付き条件」と呼んでいるものについて、意見や代替案を持っている人はいますか? :)

乾杯、マット。

4

2 に答える 2

5

どうですか:

WHERE
     interval_start <= CASE mode
                         WHEN 0 THEN '9999-12-31'
                         WHEN 1 THEN GETDATE()
                         WHEN 2 THEN GETDATE() - interval_period
                       END
于 2009-04-21T11:46:14.520 に答える
4

もう 1 つのオプションは、3 つの個別のクエリを実行し、それらを一緒に UNION することです。インデックスとテーブルの構造によっては、WHERE 句の句を OR したり、CASE ステートメントを使用したりするよりも効率的な SQL につながる可能性がありますが、それは純粋にオプティマイザを操作することになります。

3 つのアプローチすべてをテストし、最適な方法を選択します。

于 2009-04-21T11:47:19.010 に答える