我有一张桌子,让我们称它为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。
答案 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行之前,减速并不明显。
如果您将展示的策略直接用于完整查询(而不是作为独立视图),您可能会看到更好的性能,因为需要排序的行数将减少到最小值。