SQL Server-范围号

Nav*_*mar 1 sql t-sql sql-server sql-server-2012

我需要您的帮助,才能从给定的输入中获取以下输出。

输入项

表: Sample

ID
---
1
2
3
4
Run Code Online (Sandbox Code Playgroud)

输出量

ID
---
1
2
2
3
3
3
4
4
4
4
Run Code Online (Sandbox Code Playgroud)

for*_*pas 7

自我加入:

select s.id
from sample s inner join sample ss
on s.id >= ss.id 
order by s.id
Run Code Online (Sandbox Code Playgroud)

参见演示
结果:

> | id |
> | -: |
> |  1 |
> |  2 |
> |  2 |
> |  3 |
> |  3 |
> |  3 |
> |  4 |
> |  4 |
> |  4 |
> |  4 |
Run Code Online (Sandbox Code Playgroud)

如果ID之间存在间隙或最小值大于1,则可以使用递归CTE:

declare @maxid int = (select max(id) from sample);
with allids AS (
  select 1 id
  union all
  select id + 1 FROM allids where id + 1 <= @maxid
)
select s.id
from sample s inner join allids ss
on s.id >= ss.id
order by s.id
Run Code Online (Sandbox Code Playgroud)

参见演示

INSERT INTO Sample ( ID ) VALUES ( 2 ), ( 3 ), ( 5 ), ( 7 ), ( 9 );
Run Code Online (Sandbox Code Playgroud)

结果:

> | id |
> | -: |
> |  2 |
> |  2 |
> |  3 |
> |  3 |
> |  3 |
> |  5 |
> |  5 |
> |  5 |
> |  5 |
> |  5 |
> |  7 |
> |  7 |
> |  7 |
> |  7 |
> |  7 |
> |  7 |
> |  7 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
> |  9 |
Run Code Online (Sandbox Code Playgroud)

使用此解决方案,您不必对表的ID进行硬编码(它们可以是多少?),即使您添加或删除ID也可以使用


Sam*_*ami 6

这是一个解决方案

SELECT ID
FROM (VALUES (1), (2), (3), (4)) T(ID)
CROSS APPLY
(
  SELECT 1 N
  FROM master..spt_values
  WHERE [Type] = 'P'
        AND
        [Number] < T.ID
) TT(V);
Run Code Online (Sandbox Code Playgroud)

演示版

为什么使用spt_values而不是自联接?

例如,如果您没有价值 3

SELECT T.ID
FROM (VALUES (1), (2), (4)) T(ID)
INNER JOIN (VALUES (1), (2), (4)) TT(ID)
ON T.ID >= TT.ID 
ORDER BY T.ID;
Run Code Online (Sandbox Code Playgroud)

slef-join将重复该值4三次,而不是四次。使用spt_values将确保每个数字都会按预期重复。

SELECT T.ID
FROM (VALUES (1), (2), (4)) T(ID)
CROSS APPLY
(
  SELECT 1 N
  FROM master..spt_values
  WHERE [Type] = 'P'
        AND
        [Number] < T.ID
) TT(V);
Run Code Online (Sandbox Code Playgroud)

演示版


如果您有很多数字,则可以使用Tally Table作为

CREATE VIEW Tally (N) AS
SELECT ROW_NUMBER() OVER(ORDER BY(SELECT 0)) N
FROM (
       (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T1(N) --10
       CROSS JOIN
       (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T2(N) --100
       CROSS JOIN
       (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T3(N) --1000
       CROSS JOIN
       (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) T5(N) --10000
     );
SELECT T.V
FROM (VALUES (1), (2), (4), (80), (4000)) T(V)
CROSS APPLY (SELECT N FROM Tally WHERE N <= T.V) TBL
ORDER BY T.V;
Run Code Online (Sandbox Code Playgroud)

这是一个db <>小提琴