1

TIMESTAMP WITH TIME ZONEいくつかの追加情報とともに列を持つテーブルがいくつかあります。これらのテーブルを結合して、各行のすべての情報が特定の日時ウィンドウ (ラベル付けbeginendれ、目的の結果セット内) の時点で「有効」になるようにする必要があります。

私の現在のアプローチ:

オプション1

  1. ユニークな時間のリストを作成します。
  2. 各時点を、一意のリスト (「有効な」時間ウィンドウ) および元の各テーブルの時間ウィンドウに変換します。[ LEAD(...) OVER (...)]
  3. 元のテーブルを一意の時間リストに結合します。

オプション #2

  1. 各時点 ( TIMESTAMP WITH TIME ZONE) を各テーブルの時間枠に変換します。[ LEAD(...) OVER (...)]
  2. ウィンドウが重なっているテーブルを結合します。
  3. GREATEST(foo.start, bar.start)各ウィンドウから&を返しLEAST(foo.stop, bar.stop)て、真の「有効な」ウィンドウを見つけます。

例えば:

表:フー

  fooid  |  description  |       datetime
---------|---------------|-----------------------
    1    |   Varsion 1   |  2010-01-01 00:00:00  
    2    |   Varsion 2   |  2010-07-01 00:00:00 

表:バー

  barid  |  fooid  |  description  |       datetime
---------|---------|---------------|-----------------------
    1    |    1    |   Varsion A   |  2010-01-01 00:00:00
    2    |    1    |   Varsion B   |  2010-02-01 00:00:00
    3    |    1    |   Varsion C   |  2010-03-01 00:00:00
    4    |    1    |   Varsion D   |  2010-04-01 00:00:00
    5    |    1    |   Varsion E   |  2010-05-01 00:00:00
    6    |    1    |   Varsion F   |  2010-06-01 00:00:00
    7    |    2    |   Varsion A   |  2010-07-01 00:00:00
    8    |    2    |   Varsion B   |  2010-08-01 00:00:00
    9    |    2    |   Varsion C   |  2010-09-01 00:00:00
    10   |    2    |   Varsion D   |  2010-10-01 00:00:00
    11   |    2    |   Varsion E   |  2010-11-01 00:00:00
    12   |    2    |   Varsion F   |  2010-12-01 00:00:00

簡略化された望ましい結果

        begin          |          end          |  fooid  |   foo_desc    |       foostart        |        foostop        |  barid  |   bar_desc   |       foostart        |        foostop        
-----------------------|-----------------------|---------|---------------|-----------------------|-----------------------|---------|--------------|-----------------------|-----------------------
         ...           |         ...           |   ...   |      ...      |         ...           |         ...           |   ...   |     ...      |         ...           |         ...           
  2010-05-01 00:00:00  |  2010-06-01 00:00:00  |    1    |   Varsion 1   |  2010-01-01 00:00:00  |  2010-07-01 00:00:00  |    5    |  Varsion E   |  2010-05-01 00:00:00  |  2010-06-01 00:00:00
  2010-06-01 00:00:00  |  2010-07-01 00:00:00  |    1    |   Varsion 1   |  2010-01-01 00:00:00  |  2010-07-01 00:00:00  |    6    |  Varsion F   |  2010-06-01 00:00:00  |        infinity
  2010-07-01 00:00:00  |  2010-08-01 00:00:00  |    2    |   Varsion 2   |  2010-07-01 00:00:00  |       infinity        |    7    |  Varsion A   |  2010-07-01 00:00:00  |  2010-08-01 00:00:00
  2010-08-01 00:00:00  |  2010-09-01 00:00:00  |    2    |   Varsion 2   |  2010-07-01 00:00:00  |       infinity        |    8    |  Varsion B   |  2010-08-01 00:00:00  |  2010-09-01 00:00:00
         ...           |         ...           |   ...   |      ...      |         ...           |         ...           |   ...   |     ...      |         ...           |         ...           

私の質問:

これを達成するための最良の方法は何ですか?私は 2 つの異なる解決策を示すフィドルを作成しました。それぞれのアイデアと、フィドルにない可能な解決策について聞きたいと思います。

更新 #1:

この例では、結合する必要があるテーブルは 2 つだけです...ただし、場合によっては、3 つ、4 つ、またはそれ以上の複数のテーブルを結合する必要があります。

更新 #2:

オプション #1を使用した場合、私の問題は、結果セットが大きい場合、最初のサブクエリが大きくなる可能性があり、postgres がインデックスを使用できないことです。これにより、パフォーマンスが大幅に低下します。一方、それに対してできる限り最も正確LEFT OUTER JOINであり、関連するNULLデータを取り戻すことができます.

オプション #2を使用すると、クエリ プランナーはTIMESTAMP WITH TIME ZONE列のインデックスを使用できます。FROMただし、3 つ以上のテーブルを結合すると、節内でより複雑になります。句に移動できますが、関連する(table1.start, table1.stop) OVERLAPS (table2.start, table2.stop)データが失われます。WHERENULL

これはすべて、より良い方法があるかどうか疑問に思います...

4

1 に答える 1

1
  • の代わりにウィンドウ関数lead()と lag()のデフォルト値を使用しますcoalesce()

lead(datetime, 1, 'infinity') OVER (ORDER BY fooid, datetime) AS stop

それ以外の

COALESCE(LEAD(datetime) OVER (ORDER BY fooid, datetime), 'infinity'::TIMESTAMP) AS stop
  • あなたがするとき、PARTITION BY fooidそれは無意味ORDER BY fooidです。

PARTITION BY fooid ORDER BY datetime

それ以外の:

(PARTITION BY fooid ORDER BY fooid, datetime)
  • あなた(または何らかのツール)は、引用符なしですべて合法であるにもかかわらず、すべての単一の識別子を二重引用符で囲みました。クエリが読みにくくなります。ノイズを緩めます。

それ以外:あなたの質問はstackoverflowには広すぎて、説明は非常に理解しにくいです。

考慮してください: https://codereview.stackexchange.com/

于 2013-06-27T01:14:50.820 に答える