我在 sql server 2014 中有一个这样的表:
ID | Start_mile|End_mile
1 |5.23 |7.464
2 |2.333 |6.124
Run Code Online (Sandbox Code Playgroud)
我想要做的是将里程分成每个 ID 的千分之一,如下所示:
ID |start_mile|end_mile
1 |5.230 |5.231
1 |5.231 |5.232
1 |5.232 |5.233
....
1 |7.463 |7.464
...
Run Code Online (Sandbox Code Playgroud)
关于如何去做这件事的任何想法?我试图远离游标,除非这是唯一的方法。
我已经能够将这个查询放在一起,但不确定如何将它与 ID 和英里限制合并,以便它在没有声明的 From 和 To 变量的情况下为整个表运行:
DECLARE @from decimal(15, 3) = 0.980;
DECLARE @to decimal(15, 3) = 1.024;
;WITH cte AS
(SELECT @from AS Value
UNION ALL
SELECT CONVERT(decimal(15, 3), Value + 0.001)
FROM cte
WHERE Value < @to)
SELECT *
FROM cte
option (maxrecursion 0)
Run Code Online (Sandbox Code Playgroud)
如果您不想使用递归 CTE,您可以使用以下查询示例:
SELECT m.ID,
a.rn as start_mile,
a.rn+ CONVERT(decimal(15, 3),0.001) as end_mile
FROM dbo.Miles m
CROSS APPLY
(
SELECT TOP(CONVERT(int,(( end_mile - Start_mile)* 1000)))
CONVERT(decimal(15, 3),(Start_mile + (CONVERT(decimal(15, 3),ROW_NUMBER() OVER(ORDER BY (SELECT NULL))-1) / 1000))) as rn
FROM master..spt_values spt1
CROSS APPLY master..spt_values spt2
) as a;
Run Code Online (Sandbox Code Playgroud)
对于一个 ID,这应该可以运行到600 万英里。
spt 值表可以替换为某种数字表。
您只需要引用锚点中的初始开始值和结束值。
CREATE TABLE #tmp (
ID INT NOT NULL PRIMARY KEY
,[Start] DECIMAL(15, 3)
,[To] DECIMAL(15, 3)
)
GO
INSERT INTO #tmp (
ID
,[Start]
,[To]
)
VALUES (
1
,5.00
,5.99
)
,(
2
,10.00
,10.4
);
WITH cte
AS (
SELECT ID
,[Start]
,[To]
,CAST([Start] AS DECIMAL(15, 3)) AS [Value]
FROM #tmp
UNION ALL
SELECT ID
,[Start]
,[To]
,CAST(([Value] + 0.001) AS DECIMAL(15, 3))
FROM cte
WHERE CAST(([Value] + 0.001) AS DECIMAL(15, 3)) < [To]
)
SELECT *
FROM cte
ORDER BY ID
,Start
,Value
OPTION (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)