4

誰かがこの問題についての提案がありますか?、、の値が一定のままであるeffective_dtまでのスパンを統合するためにoracle SQLを使用しようとしていますが、その間の3つの列のいずれにも変更がない連続したレコードに対してのみです。expiration_dtcol_acol_bcol_c

それが役立つ場合は、次のレコードの発効日(従業員別)が前のレコードに1日を加えたものに等しいと想定しても安全です。

min()、、max()を試してみましgroup byたが、問題は以下のシナリオで12 / 1〜12/31が返されることです。lead()次に、関数を試してみましたが、問題は、統合する必要のあるレコードの数が事前にわからないことです。

以下の形式でデータを取得できると仮定します。

+----------+--------------+---------------+---------+---------+---------+
| employee | effective_dt | expiration_dt |  col_a  |  col_b  |  col_c  |
+----------+--------------+---------------+---------+---------+---------+
|     0001 | 12/1/2012    | 12/4/2012     | value_a | value_a | value_a |
|     0001 | 12/5/2012    | 12/6/2012     | value_a | value_a | value_a |
|     0001 | 12/7/2012    | 12/10/2012    | value_a | value_a | value_a |
|     0001 | 12/11/2012   | 12/17/2012    | value_a | value_b | value_a |
|     0001 | 12/18/2012   | 12/31/2012    | value_a | value_a | value_a |
+----------+--------------+---------------+---------+---------+---------+    

期待される結果:

+----------+--------------+---------------+---------+---------+---------+
| employee | effective_dt | expiration_dt |  col_a  |  col_b  |  col_c  |
+----------+--------------+---------------+---------+---------+---------+
|     0001 | 12/1/2012    | 12/10/2012    | value_a | value_a | value_a |
|     0001 | 12/11/2012   | 12/17/2012    | value_a | value_b | value_a |
|     0001 | 12/18/2012   | 12/31/2012    | value_a | value_a | value_a |
+----------+--------------+---------------+---------+---------+---------+

試行1:

SELECT employee,
  MIN(effective_dt),
  MAX(expiration_dt),
  col_a,
  col_b,
  col_c
FROM
  (SELECT employee, effective_dt, ... FROM table_x, table_y, ... where...
  ) table_a
GROUP BY employee,
  col_a,
  col_b,
  col_c;

試行2:

SELECT employee,
  effective_dt,
  lead(expiration_dt, 1) over (partition BY employee, col_a, col_b, col_c order by effective_dt) expiration_dt,
  col_a,
  col_b,
  col_c
FROM
  (SELECT employee, effective_dt, ... FROM table_x, table_y, ... where...
  ) table_a;

ありがとう!

4

1 に答える 1

1

ご指摘のとおり、次のレコードが前のレコード+ 1日と等しいと安全に想定できる場合は、これらのレコードを連鎖させることができます。

SQLフィドル

Oracle 11g R2スキーマのセットアップ

CREATE TABLE t
    (employee int, effective_dt timestamp, expiration_dt timestamp, col_a varchar2(7), col_b varchar2(7), col_c varchar2(7))
;

INSERT ALL 
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '01-Dec-2012 12:00:00 AM', '04-Dec-2012 12:00:00 AM', 'value_a', 'value_a', 'value_a')
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '05-Dec-2012 12:00:00 AM', '06-Dec-2012 12:00:00 AM', 'value_a', 'value_a', 'value_a')
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '07-Dec-2012 12:00:00 AM', '10-Dec-2012 12:00:00 AM', 'value_a', 'value_a', 'value_a')
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '11-Dec-2012 12:00:00 AM', '17-Dec-2012 12:00:00 AM', 'value_a', 'value_b', 'value_a')
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '18-Dec-2012 12:00:00 AM', '19-Dec-2012 12:00:00 AM', 'value_a', 'value_b', 'value_a')
    INTO t (employee, effective_dt, expiration_dt, col_a, col_b, col_c)
         VALUES (0001, '20-Dec-2012 12:00:00 AM', '31-Dec-2012 12:00:00 AM', 'value_a', 'value_a', 'value_a')
SELECT * FROM dual
;

クエリ1

select employee, min(effective_dt), max(expiration_dt), col_a, col_b, col_c 
  from ( select t.*, 
                case when
                     col_a = lag(col_a) over (partition by employee order by expiration_dt asc)    
                 and col_b = lag(col_b) over (partition by employee order by expiration_dt asc) 
                 and col_c = lag(col_c) over (partition by employee order by expiration_dt asc) 
                then 0 else 1 end start_of_chain 
           from t
  )
 connect by effective_dt = prior expiration_dt + 1  and start_of_chain = 0  
   start with start_of_chain = 1
   group by connect_by_root(effective_dt), employee, col_a, col_b, col_c
order by 2 

結果

| EMPLOYEE |               MIN(EFFECTIVE_DT) |              MAX(EXPIRATION_DT) |   COL_A |   COL_B |   COL_C |
--------------------------------------------------------------------------------------------------------------
|        1 | December, 01 2012 00:00:00+0000 | December, 10 2012 00:00:00+0000 | value_a | value_a | value_a |
|        1 | December, 11 2012 00:00:00+0000 | December, 19 2012 00:00:00+0000 | value_a | value_b | value_a |
|        1 | December, 20 2012 00:00:00+0000 | December, 31 2012 00:00:00+0000 | value_a | value_a | value_a |
于 2012-12-12T04:14:07.007 に答える