迭代生成数值

时间:2011-04-12 09:54:58

标签: sql sql-server

我有一张桌子,让我们称它为Foo,表格中有一个名为Bar的字段,还有一个名为LoremIpsum的字段。

Bar是一个nvarchar,但我只对可转换为整数的Bar值感兴趣。

LoremIpsum也是一个数字。

我想从我的Foo表中获取以k开头的前n个(值)数字,其中LoremIpsum具有特定值(LoremIpsum1)和(值)不在Foo的选择栏中,其中LoremIpsum = LoremIpsum1

我的输入是:(LoremIpsum1,n,k)

其中LoremIpsum1是LoremIpsum的特定值,n是要获取的数字的数量,k是偏移量。

我的输出应该是一组数字,如果LoremIpsum = LoremIpsum1,则表格中不存在Bar值。我目前的命令:

WITH    q AS
        (
        SELECT convert(bigint, 50000) AS num
        UNION ALL
        SELECT  convert(bigint, num + 1)
        FROM    q
        )
SELECT  top 200 *
FROM    q
where convert(bigint, num) not in (select convert(bigint, Bar) from Foo where LoremIpsum = 68 and isnumeric(Bar + 'e0') = 1)
option (maxrecursion 365);

此查询并不总是有效,在计算机上问题是nvarchar无法转换为bigint,可能是设置有问题,如果所需的递归比给出maxrecursion。

在这种情况下,n = 200,k = 50000,LoremIpsum1 = 68

主要问题是此查询是递归的,我想将其修改为迭代查询。

非常感谢任何帮助。

祝你好运, Lajos Arpad。

2 个答案:

答案 0 :(得分:2)

您可以使用具有足够数字的永久号码表,而不是递归cte。

create table NumberTable(Num int primary key)

您可以使用递归cte填充数字表。因为这只是一次性的事情,性能不应该那么大,如果它是你可以看看here

WITH    q AS
        (
        SELECT 0 AS num
        UNION ALL
        SELECT  num + 1
        FROM    q
        )
insert into NumberTable(Num)        
select top 10000 num
from q
option (maxrecursion 0) 

使用查询中的数字表和偏移量。

declare @n int = 200
declare @k int = 50000

SELECT  top (@n) num+@k
FROM    NumberTable
--where convert(bigint, num+k) not in (select ...

答案 1 :(得分:1)

以下视图最多可以产生2 ^ 32个数字,如果需要,可以扩展为更多:

create view numbers AS
with
  n as (select 0 as n union select 1)
, nn as (select 0 as n from n as n1, n as n2, n as n3, n as n4)
, nnn as (select 0 as n from nn as n1, nn as n2, nn as n3, nn as n4)
, nnnn as (select 0 as n from nnn as n1, nnn as n2)
select row_number() over (order by n) AS n from nnnn

go

select n from numbers where n <= 50000

令人遗憾的是,查询计划中存在一个排序阶段,因此当 n 变得非常大时,它会开始显着减慢。但是,在我的台式机上,在产生大约1,000,000行之前,减速并不明显。

如果您将展示的策略直接用于完整查询(而不是作为独立视图),您可能会看到更好的性能,因为需要排序的行数将减少到最小值。