2

残念ながら、CROSS APPLY を使用できない Vertica を使用しています。Vertica には CTE のようなものはないようです。

これが私が持っているものです:

t:
    day    | id | metric | d_metric
-----------+----+--------+----------
2011-12-01 |  1 | 10     | 10
2011-12-03 |  1 | 12     | 2
2011-12-04 |  1 | 15     | 3

初日のデルタはメトリック値と等しいことに注意してください。次のように、ギャップを埋めたいと思います。

t_fill:
    day    | id | metric | d_metric
-----------+----+--------+----------
2011-12-01 |  1 | 10     | 10
2011-12-02 |  1 | 10     | 0 -- a delta of 0
2011-12-03 |  1 | 12     | 2
2011-12-04 |  1 | 15     | 3

私はこれを毎日行う方法を考えてきましたが、私が本当に望んでいるのは、一度に機能するソリューションです。

LAST_VALUE で何かを動作させることができると思いますが、各 ID の日々の履歴を適切に分割して順序付けできる適切な JOIN ステートメントを思い付くことができません。

編集:次のようなテーブルがあるとします:

calendar:
    day 
------------
2011-01-01
2011-01-02
   ...

結合に関与する可能性があります。私の意図は、カレンダーの日付範囲をtの日付範囲と一致するように維持することです。

編集:具体的には、探しているものに関するいくつかのメモ:

t_fillを生成する際に、 tの日付範囲と、その間にない日付を正確にカバーしたいと思います。したがって、正しいt_fillはtと同じ日付で開始し、同じ日付で終了します。 t_fillには 2 つのプロパティがあります。

1) ある日付に ID が表示されると、以降の日付ごとに常に行が表示されます。これは、元の質問で暗示されているギャップを埋めることです。

2) ある日付以降に id の行が再び表示されない場合、t_fillソリューションは、その最後のデータ ポイントの日付からtの終了日まで、同じメトリック値 (および 0 デルタ) を持つ行を陽気に生成する必要があります。

ソリューションは、 tの日付範囲の開始までの以前の日付を埋め戻す可能性があります。つまり、 t の最初の日付の後に表示される id の場合、t最初の日付と id の最初の日付の間の行は、metric=0 と d_metric=0 で埋められます。システムに入る各IDの成長率が高いため、この種のソリューションは好みません。しかし、metric!=0 および d_metric!=0 の行のみを新しいテーブルに選択することで、簡単に対処できました。

4

4 に答える 4

1

これはJonathan Lefflerが提案したものですが、昔ながらの低レベルSQL(派手なCTEやウィンドウ関数、またはサブクエリの集約なし)です:

SET search_path='tmp'
DROP TABLE ttable CASCADE;
CREATE TABLE ttable
        ( zday date NOT NULL
        , id INTEGER NOT NULL
        , metric INTEGER NOT NULL
        , d_metric INTEGER NOT NULL
        , PRIMARY KEY (id,zday)
        );
INSERT INTO ttable(zday,id,metric,d_metric) VALUES
 ('2011-12-01',1,10,10)
,('2011-12-03',1,12,2)
,('2011-12-04',1,15,3)
        ;

DROP TABLE ctable CASCADE;
CREATE TABLE ctable
        ( zday date NOT NULL
        , PRIMARY KEY (zday)
        );
INSERT INTO ctable(zday) VALUES
 ('2011-12-01')
,('2011-12-02')
,('2011-12-03')
,('2011-12-04')
        ;

CREATE VIEW v_cte AS (
        SELECT t.zday,t.id,t.metric,t.d_metric
        FROM ttable t
        JOIN ctable c ON c.zday = t.zday
        UNION
        SELECT c.zday,t.id,t.metric, 0
        FROM ctable c, ttable t
        WHERE t.zday < c.zday
        AND NOT EXISTS ( SELECT *
                FROM ttable nx
                WHERE nx.id = t.id
                AND nx.zday = c.zday
                )
        AND NOT EXISTS ( SELECT *
                FROM ttable nx
                WHERE nx.id = t.id
                AND nx.zday < c.zday
                AND nx.zday > t.zday
                )
        )
        ;
SELECT * FROM v_cte;

結果:

    zday    | id | metric | d_metric 
------------+----+--------+----------
 2011-12-01 |  1 |     10 |       10
 2011-12-02 |  1 |     10 |        0
 2011-12-03 |  1 |     12 |        2
 2011-12-04 |  1 |     15 |        3
(4 rows)
于 2012-01-03T16:56:13.173 に答える
0

CTEのようなものを使用したい場合は、一時テーブルを使用してみませんか?基本的に、CTEは特定のクエリのビューです。

必要に応じて、一時テーブルトランザクションまたはセッションスコープを作成できます。

定数補間によるギャップフィリングがここで機能しない理由を知りたいのですが。

于 2012-01-03T15:49:40.690 に答える
0

私は Vertica ユーザーではありませんが、GAP フィリングのネイティブ サポートを使用したくない場合は、より一般的な SQL のみのソリューションを見つけることができます

于 2012-01-02T18:35:52.740 に答える
0

完全なカレンダー表があれば、実行可能ですが、それほど簡単ではありません。カレンダーテーブルがなければ、もっと大変です。

クエリは適度に正確に記述する必要があります。これは通常、「クエリの書き方」に関する問題の半分です。私はあなたが探していると思います:

  • T (またはその他の規定範囲) で表される最小日付と最大日付の間の Calendar の各日付について、
  • T で表される個別の ID ごとに、
  • 日付以前の T の最新レコードの指定された ID のメトリックを検索します。

これにより、メトリックを含む日付の完全なリストが得られます。

次に、デルタを形成するために、1 日離れた日付でそのリストの 2 つのコピーを自己結合する必要があります。

日付範囲の開始時に表示されない ID 値がある場合、それらは表示されないことに注意してください。

それを指針にすれば、きっとうまくいくはずです。

于 2012-01-03T16:00:04.860 に答える