Oracle SQL循环LEAD()通过分区

时间:2018-04-17 01:18:16

标签: sql oracle loops lead

我有一套看起来像这样的

ID  date_IN  date_out
1    1/1/18   1/2/18
1    1/3/18   1/4/18
1    1/5/18   1/8/18
2    1/1/18   1/5/18
2    1/7/18   1/9/18

我是从

开始的
SELECT ID, date_IN, Date_out, lead(date_out) over ( partition by (ID)
order by ID) as next_out
From table

得到这样的东西......

ID  date_IN  date_out  next_out
1    1/1/18   1/2/18   1/4/18
1    1/3/18   1/4/18   1/8/18
1    1/5/18   1/8/18    Null
2    1/1/18   1/5/18    1/9/18
2    1/7/18   1/9/18   Null

我将要遇到的问题是,在我的实际数据中,许多ID都有很多条目。目标是让所有date_out出现在每个ID的一行....

ID  date_IN  date_out  next_out  next_out1  etc.   etc.
1    1/1/18   1/2/18   1/4/18     1/8/18     X      X
2    1/1/18   1/5/18   1/7/18     X         Null    Null

有没有办法将lead()循环到整个分区,按ID顺序删除除第一行之外的所有内容然后转到下一个ID?

3 个答案:

答案 0 :(得分:0)

无需循环但使用偏移选项。以下是从文档中解除的。

offset
Optional. It is the physical offset from the current row in the table.
If this parameter is omitted, the default is 1.

example; lead(date_out) means next value
lead(date_out, 2) means 2nd row after current row
lead(date_out, 3) 3rd row after current row and so on.
你的代码中的

;使用下面的代码段;

lead(date_out) over ( partition by (ID) order by ID) as next_out,
lead(date_out, 2) over ( partition by (ID) order by ID) as next_out2,
lead(date_out, 3) over ( partition by (ID) order by ID) as next_out3

答案 1 :(得分:0)

这是一种方法,假设您只希望每ID个最多有三个日期对。您可以指定行号,然后按ID汇总:

WITH cte AS (
    SELECT ID, date_IN, date_out,
        ROW_NUMBER() OVER (PARTITION BY ID ORDER BY date_IN) rn
    FROM yourTable
)

SELECT
    ID,
    MAX(CASE WHEN rn = 1 THEN date_IN END) AS date_IN,
    MAX(CASE WHEN rn = 1 THEN date_out END) AS date_out,
    MAX(CASE WHEN rn = 2 THEN next_IN END) AS next_in_1,
    MAX(CASE WHEN rn = 2 THEN date_out END) AS next_out_2,
    MAX(CASE WHEN rn = 3 THEN date_IN END) AS next_in_2,
    MAX(CASE WHEN rn = 3 THEN date_out END) AS next_out_2
FROM cte
GROUP BY ID

答案 2 :(得分:0)

   WITH TAB AS(
SELECT 1 ID,  CAST('2018/01/01' AS DATE) DATE_IN, CAST('2018/01/02' AS DATE) DATE_OUT FROM DUAL
UNION
SELECT 1, CAST('2018/01/03' AS DATE)   , CAST('2018/01/04' AS DATE) FROM DUAL
UNION
SELECT 1, CAST('2018/01/05' AS DATE)   , CAST('2018/01/08' AS DATE) FROM DUAL
UNION
SELECT 1, CAST('2018/01/09' AS DATE)   , CAST('2018/01/10' AS DATE) FROM DUAL
UNION
SELECT 1, CAST('2018/01/11' AS DATE)   , CAST('2018/01/12' AS DATE) FROM DUAL
UNION
SELECT 2, CAST('2018/01/01' AS DATE)   , CAST('2018/01/05' AS DATE) FROM DUAL
UNION
SELECT 2, CAST('2018/01/07' AS DATE)   , CAST('2018/01/09' AS DATE) FROM DUAL
) --select * from tab;
, LEAF_CALC AS(   --CONNECTING THE DATE_OUTS
SELECT 
ID
,SYS_CONNECT_BY_PATH(DATE_OUT, '$') HRCHY
, LEVEL LVL
, CONNECT_BY_ISLEAF ISLEAF
FROM TAB
CONNECT BY PRIOR DATE_OUT < DATE_IN 
START WITH ID = 1
) --SELECT * FROM LEAF_CALC;
, DATA_SORT AS( --ADDING ALL DATE_OUTS IN 1 ROW
SELECT
P.ID, P.HRCHY
FROM LEAF_CALC P,
(SELECT ID, MAX(LVL) MAXLVL FROM
LEAF_CALC
GROUP BY ID) C
WHERE P.ID = C.ID 
AND P.LVL = C.MAXLVL
)--SELECT * FROM DATA_SORT
--SEGREGATING ALL DATES USING REGEXP_SUBSTR
SELECT
ID
, REGEXP_SUBSTR(HRCHY, '[^$]+', 1, 1) DATE_IN
, REGEXP_SUBSTR(HRCHY, '[^$]+', 1, 2) NEXT_OUT
, REGEXP_SUBSTR(HRCHY, '[^$]+', 1, 3) NEXT_OUT2
, COALESCE(REGEXP_SUBSTR(HRCHY, '[^$]+', 1, 4), 'NA') NEXT_OUT3
, COALESCE(REGEXP_SUBSTR(HRCHY, '[^$]+', 1, 5), 'NA') NEXT_OUT4
FROM DATA_SORT;