我有一张产品订单属性表。
OrderId | SerialFrom | Serial To
1 | 6605181145833976 | 6605181145833980
如何以这种方式显示它:
SerialId
6605181145833976
6605181145833977
6605181145833978
6605181145833979
谢谢。
答案 0 :(得分:1)
您需要递归 CTE
作为
CREATE TABLE Data(
OrderId INT,
SerialFrom BIGINT,
SerialTo BIGINT
);
INSERT INTO Data VALUES
(1, 6605181145833976, 6605181145833980);
WITH CTE AS
(
SELECT SerialFrom
FROM Data
UNION ALL
SELECT SerialFrom + 1
FROM CTE
WHERE CTE.SerialFrom < 6605181145833979
)
SELECT SerialFrom SerialId
FROM CTE;
返回:
+------------------+
| SerialId |
+------------------+
| 6605181145833976 |
| 6605181145833977 |
| 6605181145833978 |
| 6605181145833979 |
+------------------+
由于已知行数,并且只有4个值,因此您也可以将 Table Value Constructor
(在这种情况下,这是最佳选择)用作
SELECT SerialFrom + Number SerialId
FROM Data D CROSS JOIN
(VALUES (0), (1), (2), (3)) T(Number);
您还可以对master..spt_values
系统表执行以下操作
SELECT SerialFrom + Number SerialId
FROM Data D CROSS JOIN
master..spt_values T
WHERE T.[Type] = 'P'
AND
[Number] <= 3;
有鉴于此,我建议不要使用master..spt_values
系统表,因为它没有记录,并且Microsoft可以在不警告的情况下更改未记录的系统表,因此应避免使用它们。仍然是您的选择:)。
最后,这是一个 db<>fiddle
,可以用来查看其工作原理。
答案 1 :(得分:0)
数字计数表会有所帮助。它可以是预定义的表,也可以根据以下查询动态创建。
with L0(N) as (
select top(10) null from sys.all_objects
),L1(N) as (-- 10**2
select null
from L0 a1
cross join L0 a2
),L2(N) as (-- 10**2**2
select null
from L1 a1
cross join L1 a2
), tally as(
select n = row_number() over(order by N) - 1
from L2
)
select OrderId, SerialFrom + n
from Mytable mt
join tally t on t.n <= SerialTo - SerialFrom