SQL Server - 在按特定列分组时构建动态范围的数字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server - 在按特定列分组时构建动态范围的数字相关的知识,希望对你有一定的参考价值。

我有以下数据:

ID                        Days
-----------------------   --------
1                         5
1                         10
1                         15

2                         5
2                         13
2                         15

我试图根据他们的ID进行分组,根据日期建立一系列数字。

对于ID组1:范围从5开始到9结束。下一个范围是10-14,然后最终范围是15-9999

对于ID组2:范围从5开始到12结束。下一个范围是13-14,然后最终范围是15-9999

结果表看起来像这样:

RangeStart  RangeEnd    RangeText   ID                                           
----------- ----------- ---------  ----
5           9           5 - 9         1                  
10          14          10 - 14       1     
15          9999        15 - 9999     1       
5           12          5 - 12        2                  
13          14          13 - 14       2     
15          9999        15 - 9999     2  

我试图使用CTE,但只有当我没有按ID分组时才有效。

Declare @RangeTable Table
(
ID Int,
RangeStart INT,
RangeEnd INT,
RangeText Varchar(50),
);with CTE as (
SELECT temp.Days,
rn = ROW_NUMBER() over(order by temp.Days asc),
temp.ID
FROM @TableWithDays temp)


INSERT @RangeTable
SELECT 
    ID= d1.ID,
    RangeStart= ISNULL(d1.Days, 0),
    RangeEnd  = ISNULL(d2.Days- 1, 9999),
    RangeText = 
    CASE WHEN (d1.Days = d2.Days - 1) 
    THEN CAST(d1.Days AS VARCHAR(100)) 
    ELSE
    ISNULL(CAST(d1.Days AS VARCHAR(100)),'0') + ISNULL(' - '+ 
    CAST(d2.Days - 1 AS VARCHAR(100)),' - 9999')END
FROM
CTE d1 LEFT JOIN
CTE d2 
   ON d1.rn = d2.rn - 1
答案

您可以使用递归CTE。这对lead()来说会更简单,但是没有。所以:

with t as (
      select t.*, t2.days as next_days
      from @TableWithDays t outer apply
           (select top (1) t2.*
            from @TableWithDays t2
            where t2.id = t.id and t2.days > t.days
            order by t2.days desc
           ) t2
     ),
     cte as (
      select t.id, t.days, t.next_days
      from t
      union all
      select cte.id, cte.days + 1, cte.next_days
      from cte
      where cte.days < cte.next_days or
            (cte.days < 9999 and cte.next_days is null)
     )
select *
from cte
with option (maxrecursion 0);

以上是关于SQL Server - 在按特定列分组时构建动态范围的数字的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 动态行转列(参数化表名分组列行转列字段字段值)

根据 SQL Server 2008 R2 中特定列中的模式更改对行进行分组

SQL Server 动态行转列(参数化表名分组列行转列字段字段值)

在按两列分组时选择最大值,并在另一列上排序

SQL Server:聚合时,为特定列选择单行的值

SQL Server:减去相邻列分组