表有
Vendor_ID Warrant_ID
1 100
1 101
1 102
1 105
2 106
2 108
2 109
2 110
2 111
2 115
3 120
3 125
我需要显示
Vendor_id Warrant_seq_begin Warrant_seq_end Gap
1 100 102 0
1 105 105 2
2 106 106 0
2 108 111 1
2 115 115 3
3 120 125 4
答案 0 :(得分:1)
这可能有助于提出一些想法。它给出了没有差距的结果:
SELECT vendor_id
,MIN(ws_begin) AS warrant_seq_begin
,NVL(MAX(ws_end), MIN(ws_begin)) AS warrant_seq_end
FROM ( SELECT vendor_id
,CASE WHEN seq_start <> 0 THEN warrant_id ELSE NULL END AS ws_begin
,CASE WHEN seq_start = 0 THEN warrant_id ELSE NULL END AS ws_end
,SUM(seq_start) OVER(ORDER BY vendor_id, warrant_id) AS grouping
FROM (
SELECT vendor_id
,warrant_id
,NVL(lag(warrant_id) OVER(PARTITION BY vendor_id ORDER BY warrant_id), warrant_id) AS prev_warrant_id
,CASE WHEN NVL(lag(warrant_id) over(PARTITION BY vendor_id ORDER BY warrant_id), warrant_id) + 1 <> warrant_id THEN 1 ELSE 0 END AS seq_start
FROM my_table
ORDER BY 1, 2, 4
)
)
GROUP BY vendor_id, grouping
ORDER BY vendor_id, grouping
结果:
VENDOR_ID WARRANT_SEQ_BEGIN WARRANT_SEQ_END
1 100 102
1 105 105
2 106 106
2 108 111
2 115 115
3 120 120
3 125 125
如果你开始查看最内层查询的结果并解决问题,可能最容易理解。最里面的查询只想在“序列”被破坏的任何时候标记:
VENDOR_ID WARRANT_ID PREV_WARRANT_ID SEQ_START
1 100 100 1
1 101 100 0
1 102 101 0
1 105 102 1
2 106 106 1
2 108 106 1
2 109 108 0
2 110 109 0
2 111 110 0
2 115 111 1
3 120 120 1
3 125 120 1
下一级别(中间查询)对上一个查询的标志进行求和以创建分组:
VENDOR_ID WS_BEGIN WS_END GROUPING
1 100 (null) 1
1 (null) 101 1
1 (null) 102 1
1 105 (null) 2
2 106 (null) 3
2 108 (null) 4
2 (null) 109 4
2 (null) 110 4
2 (null) 111 4
2 115 (null) 5
3 120 (null) 6
3 125 (null) 7
我们的想法是将其分解为分组,构建稀疏矩阵,然后压缩矩阵。
答案 1 :(得分:1)
这是使用密集排名,其中samples是您的样本表,查询给出了您想要的结果: -
select Vendor_ID,series_frm,series_to,
series_frm-nvl(lag(series_to) over
(partition by Vendor_ID order by series_to)+1,series_frm) gaaap
from
(
SELECT Vendor_ID,MIN(Warrant_ID) series_frm, MAX(Warrant_ID) series_to
FROM ( SELECT Vendor_ID,Warrant_ID,
Warrant_ID - dense_rank() OVER(ORDER BY Warrant_ID) series
FROM sampled
) tab
GROUP BY Vendor_ID,series
)
order by 1,2;