Oracle SQL Query显示序列开始编号和结束编号

时间:2014-12-15 23:23:33

标签: sql oracle

表有

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

2 个答案:

答案 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;