Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何为特定数字范围生成十进制数字序列_Sql_Sql Server - Fatal编程技术网

Sql 如何为特定数字范围生成十进制数字序列

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.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
         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;