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

时间:2016-10-25 08:50:08

标签: sql sql-server

请考虑以下问题的示例。 假设我们有一系列十进制数,如package main import ( "fmt" "os" "os/exec" ) func main(){ cpuMap := "0xA00000800000" cpuIds = getCpuIds(cpuMap) fmt.Println(cpuIds) } func getCpuIds(cpuMap string) string { // getting the cpu ids cpu_ids_i, _ := strconv.ParseInt(cpuMap, 0, 64) // int from string cpu_ids_b := strconv.FormatInt(cpu_ids_i, 2) // binary as string var buff bytes.Buffer for i, runeValue := range cpu_ids_b { // take care! go returns code points and not the string if runeValue == '1' { //fmt.Println(bitString, i) buff.WriteString(fmt.Sprintf("%d", i)) } if (i+1 < len(cpu_ids_b)) && (runeValue == '1') { //fmt.Println(bitString) buff.WriteString(string(",")) } } cpuIds := buff.String() // remove last comma cpuIds = cpuIds[:len(cpuIds)-1] //fmt.Println(cpuIds) return cpuIds } 我希望结果为

(12.50 ,13.20 etc.)

要生成最多5个小数位。 在sql中可以吗?

4 个答案:

答案 0 :(得分:3)

以下是使用Recursive CTE

的一个技巧

Cast将您的数据添加到5的{​​{1}}小数位,以获得所需格式的结果

CTE

在您的预期结果中,数据从;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) 开始,尽管您的样本数据从12.51001开始。如果您确实需要从12.50开始,请将12.51001添加到0.01001

的源查询中
CTE

答案 1 :(得分:2)

使用数字表或递归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)

答案 2 :(得分:2)

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) 

答案 3 :(得分: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秒才能生成相同的设置。