2017-01-10 9 views
0

Iはタイプ2の緩やかに変化するディメンション変換(テラ14.10)

KeyField DeltaField SomeField Row_Ins_Ts 
1  a   1   '2016-01-01 00:00:00' 
1  a   2   '2016-01-02 00:00:00' 
1  b   3   '2016-01-03 00:00:00'   
1  a   4   '2016-01-04 00:00:00' 
2  d   5   '2016-01-01 00:00:00' 
2  d   6   '2016-01-02 00:00:00' 
2  e   7   '2016-01-03 00:00:00' 
2  e   8   '2016-01-04 00:00:00' 

ようなテーブルは、私はDeltaFieldの各値が所定KeyFieldの現在た間隔を取得する必要があります。上記のデータ・セットの設定

結果は次のようになります。

KeyField DeltaField Rec_Strt_Ts   Rec_End_Ts 
1  a   '2016-01-01 00:00:00' '2016-01-02 23:59:59' 
1  b   '2016-01-03 00:00:00' '2016-01-03 23:59:59'  
1  a   '2016-01-04 00:00:00' '9999-12-31 23:59:59' 
2  d   '2016-01-01 00:00:00' '2016-01-02 23:59:59' 
2  e   '2016-01-03 00:00:00' '9999-12-31 23:59:59' 

答えて

1

私はにVerticaの代わりのTeradataでこれをしようとしているが、両方は幸いANSI 99標準サポートしています。また、OLAPまたは分析と呼ばれるウィンドウ関数を、複数のグローバル表の式を使用してWITH句を定義します。

最初のグローバルテーブル式は、サンプルデータを生成するだけです。 OLAP関数を通常WHERE句に入れることはできず、したがって、それを副選択で取得する必要があるため、2番目はクエリに属します。また、LOB()OLAP関数は、前のものと同じを持つ行を除外できるようにするために必要な機能です。したがって、最後のクエリでは、deltafield <> prev_deltafieldをフィルタリングし、LEAD()OLAP関数を使用して1秒を引いて終了タイムスタンプを取得します。私はIFNULL()関数を使って、LEAD()またはLAG()の値がない状況に対応します。 IFNULL()の同義語にはNVL()またはVALUE()を使用できます。 COALESCE()も動作しますが、引数の数が可変であるため速度が遅くなります。ここを参照してください:

WITH foo(keyfield,deltafield,somefield,row_ins_ts) AS (
      SELECT 1,'a',1, TIMESTAMP '2016-01-01 00:00:00' 
UNION ALL SELECT 1,'a',2, TIMESTAMP '2016-01-02 00:00:00' 
UNION ALL SELECT 1,'b',3, TIMESTAMP '2016-01-03 00:00:00' 
UNION ALL SELECT 1,'a',4, TIMESTAMP '2016-01-04 00:00:00' 
UNION ALL SELECT 2,'d',5, TIMESTAMP '2016-01-01 00:00:00' 
UNION ALL SELECT 2,'d',6, TIMESTAMP '2016-01-02 00:00:00' 
UNION ALL SELECT 2,'e',7, TIMESTAMP '2016-01-03 00:00:00' 
UNION ALL SELECT 2,'e',8, TIMESTAMP '2016-01-04 00:00:00' 
) 
, add_previous_deltafield AS (
SELECT 
    keyfield 
, deltafield 
, LAG(deltafield) OVER(PARTITION BY keyfield ORDER BY row_ins_ts) AS prev_deltafield 
, row_ins_ts 
FROM foo 
) 
SELECT 
    keyfield 
, deltafield 
, row_ins_ts AS rec_start_ts 
, IFNULL(
    LEAD(row_ins_ts) OVER(
     PARTITION BY keyfield ORDER BY row_ins_ts 
    ) - INTERVAL '1 SECOND' 
    , '9999-12-31 23:59:59' 
) AS rec_end_ts 
FROM add_previous_deltafield 
WHERE deltafield <> IFNULL(prev_deltafield,'') 
ORDER BY keyfield; 

をハッピープレイ - マルコ・セイン

+0

美しい、あなたに感謝を! –

1

(彼らはポータブルなので、いいです)ウィンドウ関数の代わりに、Teradataのの期間のロジックに組み込まれただけでなく、いくつかの組み込みを使用することができますこれに迅速に取り組むための機能を備えています。

基本的にこれは、3つの部分になります:あなたのタイムスタンプが期間(タイムスタンプ)に変換

  1. を。 Teradataの期間タイプには開始点と終了点があり、形式はPeriod(<begindate>, <enddate>)で、日付またはタイムスタンプを使用します。
  2. 組み込み関数TD_NORMALIZE_OVERLAP_MEETを使用すると、フィールドに基づいて重複または会議期間の複数のレコードをまとめて圧縮できます。
  3. それから、その関数の結果である期間の始めを取る。あなたの例では

WITH subtbl(keyfield, deltafield, durations) AS 
(
    SELECT 
     keyfield, 
     deltafield, 
     PERIOD(row_ins_ts, row_ins_ts + INTERVAL '1' DAY) AS durations 
    FROM 
     <yourtable> 
) 
SELECT keyfield, deltafield, BEGIN(durations) 
FROM TABLE 
    (
     TD_NORMALIZE_OVERLAP_MEET (NEW VARIANT_TYPE(subtbl.keyfield, subtbl.deltafield), subtbl.durations) 
     RETURNS (keyfield INTEGER, deltafield CHAR(1), durations PERIOD(TIMESTAMP(0)), numRecords INTEGER) 
     HASH BY keyfield, deltafield 
     LOCAL ORDER BY keyfield, deltafield, durations 
    ) AS dt(keyfield, deltafield, durations, numRecords)  
ORDER BY 1, 2; 

出力:

+----------+------------+------------------+ 
| keyfield | deltafield | BEGIN(durations) | 
+----------+------------+------------------+ 
|  1 | a   | 1/4/2016 0:00 | 
|  1 | a   | 1/1/2016 0:00 | 
|  1 | b   | 1/3/2016 0:00 | 
|  2 | d   | 1/1/2016 0:00 | 
|  2 | e   | 1/3/2016 0:00 | 
+----------+------------+------------------+ 
関連する問題