1

3 つの列を持つテーブルがあるとします。

  1. イベント ID (PK)
  2. タグ名
  3. タグ値

次のような結果になるクエリを作成する必要があります。

  1. イベントID
  2. タグ名
  3. タグ値
  4. 前の条件タグ
  5. 前の条件値

PreviousConditionTag/Value は、前の行の TagName および TagValue からのものです (EventID 順の場合)。

この問題の単純なバージョンでは、PreviousConditionTag は常に TagName と同じでした。つまり、現在の TagName の以前の値を取得するだけで済みました。これは、Oracle の LAG 分析関数を使用して解決し、TagName でパーティション分割しました。

ただし、同様のことを実行する必要がありますが、TagName と PreviousConditionTag の関係が 1 対 1 ではない別のテーブルによって、PreviousConditionTag が TagName に関連付けられた任意のタグである場合です。

たとえば、特定の行の TagName が「ABC」の場合、関係テーブルは「IJK」または「XYZ」のいずれかの前の値を検索する必要があると言う場合があります。

同じテーブルに対して SELECT を実行し、条件に一致する MAX(EventID) を探す Oracle 関数でこのロジックを思いつくことができました。例えば:

SELECT * FROM MyTable WHERE EventID = (
    SELECT MAX(EventID) FROM MyTable WHERE TagName IN (
        SELECT ConditionTagName FROM ConditionMappingTable WHERE TagName = [CurrentTagName]
    )
) AND EventID <= [CurrentEventId]

ただし、ご想像のとおり、このクエリは MyTable の行ごとに関数で実行されるため、そのパフォーマンスが気になります。

Oracle の LAG 分析を再度使用する方法を考えようとしていましたが、パーティションが重複しているように見えるため、そのための PARTITION 句を考え出す方法がわかりませんでした。(たとえば、タグ ABC は IJK と XYZ を確認する必要があり、タグ DEF は IJK と UVW を確認する必要があります)

何か案は?

4

1 に答える 1

1

これは、よりよく理解できるようになったので、答えを書き直したものです。

重複するタグのセットを検索し、それでも前のイベント ID を取得したい。アイデアは次のとおりです。

  1. すべての現在のタグの ID をマッピング テーブルに追加します (つまり、現在のタグ = 条件タグ)。
  2. 条件タグに基づいてマッピング テーブルに結合し、一致する現在のタグを取得します。したがって、行は一致する「現在の」タグで再ラベル付けされており、これをラグに使用できます。
  3. 現在のタグで分割されたラグ ロジックに基づいて、最新の EventId を取得します。
  4. Current タグと Condition タグが同じ結果を選択します。

    select t.*
    from (select t.*, mt.CurrentTagName, mt.ConditionTagName,
             lag(EventId, 1, NULL)
             over (partition by mt.CurrentTagName
                   order by EventId)
      from t join
           (select CurrentTagName, ConditionTagName
            from ((select CurrentTagName, ConditionTagName
                   from ConditionMappingTable mt
                  ) union all
                  (select distinct CurrentTagName, CurrentTagName
                   from ConditionMappingTable mt
                  )
                 ) mt
           )
           on mt.ConditionTagName = t.tagname
     ) t
    on CurrentTagName = ConditionTagName
    

これは直感に反するように思えるかもしれません。なぜなら、現在ではなく状態によって物事を逆に調べているからです。そして、処理中の行数を掛けています。ただし、使用していた結合ソリューションよりも高速な場合があります。

于 2012-05-29T15:56:59.317 に答える