Sql 如何为特定数字范围生成十进制数字序列
考虑上面问题的以下示例。 假设我们有一系列十进制数,比如12.50、13.20等等。 我想要结果Sql 如何为特定数字范围生成十进制数字序列,sql,sql-server,Sql,Sql Server,考虑上面问题的以下示例。 假设我们有一系列十进制数,比如12.50、13.20等等。 我想要结果 12.51001 12.51002 .... 13.19999 13.20000 最多可生成小数点后5位。 在sql中可能吗?这里有一个使用递归CTE的技巧 在CTE中将数据转换为小数点后5位,以获得所需格式的结果 ;WITH cte AS (SELECT Cast(12.50 AS NUMERIC(22, 5)) AS num --Min value from your data
12.51001
12.51002
....
13.19999
13.20000
最多可生成小数点后5位。
在sql中可能吗?这里有一个使用递归CTE的技巧
在CTE中将数据转换为小数点后5位,以获得所需格式的结果
;WITH cte
AS (SELECT Cast(12.50 AS NUMERIC(22, 5)) AS num --Min value from your data
UNION ALL
SELECT Cast(num + 0.00001 AS NUMERIC(22, 5))
FROM cte
WHERE num < Cast(13.20 AS NUMERIC(22, 5))) -- Max value from your data
SELECT *
FROM cte
OPTION (maxrecursion 0)
使用数字表或递归cte
; with rcte as
(
select n = 1250000
union all
select n = n + 1
from rcte
where n < 1320000
)
select convert(decimal(10,5), n / 100000.0)
from rcte
option (maxrecursion 0)
我建议不要使用循环来生成序列,而是使用计数表。Aaron Bertrand已经测试了生成集合的各种方法,它的性能远远超过了递归CTE。事实上,递归CTE非常糟糕,它会从大多数结果中删除,因为它会使图上的比例扭曲太多 因此,您可以使用以下方法:
DECLARE @StartNumber DECIMAL(10, 5) = 12.50,
@EndNumber DECIMAL(10, 5) = 13.20,
@Increment DECIMAL(10, 5) = 0.00001;
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT 1 FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT TOP (1 + CONVERT(INT, CEILING((@EndNumber - @StartNumber) / @Increment)))
@StartNumber + ((ROW_NUMBER() OVER(ORDER BY N) - 1) * @Increment)
FROM N4;
作为您需求的快速基准,如果我将结束编号更改为23.2,则在我的机器上运行这始终需要大约4秒,递归CTE大约需要10秒来生成相同的集合。我建议使用Tall而不是递归。看,我看了,这很有趣,但我在CTE上注意到,他在SQL中输入了一个“ORDER BY n”-他真的不需要,这花了所有的时间-只需要对最终结果进行排序。理货表最终会缓存在RAM中,因此会使用资源——这就是我反对日历和数字表的原因。
DECLARE @startnum decimal(18,5)=12.50
DECLARE @endnum decimal(18,5)=13.20
set @startnum = @startnum+0.01
;WITH cte
AS (SELECT Cast(@startnum AS NUMERIC(22, 5)) AS num
UNION ALL
SELECT Cast(num + 0.00001 AS NUMERIC(22, 5))
FROM cte
WHERE num < Cast(@endnum AS NUMERIC(22, 5)))
SELECT *
FROM cte
OPTION (maxrecursion 0)
DECLARE @StartNumber DECIMAL(10, 5) = 12.50,
@EndNumber DECIMAL(10, 5) = 13.20,
@Increment DECIMAL(10, 5) = 0.00001;
WITH N1 AS (SELECT N FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (N)),
N2 (N) AS (SELECT 1 FROM N1 AS N1 CROSS JOIN N1 AS N2),
N3 (N) AS (SELECT 1 FROM N2 AS N1 CROSS JOIN N2 AS N2),
N4 (N) AS (SELECT 1 FROM N3 AS N1 CROSS JOIN N3 AS N2)
SELECT TOP (1 + CONVERT(INT, CEILING((@EndNumber - @StartNumber) / @Increment)))
@StartNumber + ((ROW_NUMBER() OVER(ORDER BY N) - 1) * @Increment)
FROM N4;