我想使用一个参数在 SQL in Clause 中传递超过 1,000 个参数,并为其创建一个临时表:
drop table if EXISTS #k_temp_table
select i.account_value
into #k_temp_table
from
(
select distinct acnt.account_value
from tablea a
join tableb b on b.account_key = a.account_key
outer apply fngetaccount(a.account_key) acnt
where b.period_end_dt > 2016-12-31
group by acnt.identifier_value
)i
select * from #k_temp_table
-- gives me all the account numbers I need- approx ~40K values.
问题-如何在 CTE 中将其作为子查询调用,因为 SQL 脚本一直运行并且没有给出结果:
with Total as (
select xyz...
from tables abc
where abc.account_value in (I am trying to use subquery here from #k_temp_table to parametrize account values)
)
我无法理解这个问题,还有其他方法可以做到这一点吗?
@JoelCoehoorn 我尝试了所有方法,但出现以下错误“无法为数据库“tempdb”中的对象“dbo.SORT 临时运行存储分配空间:155990860234752”,因为“PRIMARY”文件组由于缺乏存储空间或数据库文件而已满达到允许的最大大小。请注意,UNLIMITED 文件仍限制为 16TB。通过删除文件组中的对象、向文件组添加其他文件或为文件组中的现有文件设置自动增长来创建必要的空间。” 然后我运行这个查询 - 'select * from tempdb.sys.allocation_units' - 来查找我的分配单元限制,但是有没有其他方法可以做到这一点,因为我只有对数据库的只读访问权限。
SQL 脚本继续运行并且没有给出任何结果:
“Just keep running”意味着您编写了一个非常慢的查询。等待足够长的时间,也许你最终会看到一些东西。幸运的是,我们可以通过多种方法来极大地提高性能。
首先,您可以更改此设置以使用
JOIN
或EXISTS
查询而不是IN()
,这已经可以显着提高性能(特别是如果您对临时表建立索引):
with Total as (
select xyz...
from tables a
inner join #k_temp_table k on k.account_value = a.account_value
)
或
with Total as (
select xyz...
from tables a
where exists (select 1 from #k_temp_table k where k.account_value = a.account_value)
)
但这仍然有点弱。根本没有充分的理由为此使用临时表。虽然临时表很有用,甚至偶尔可以提高性能,但通常它们会使事情变得更慢、更复杂,并且是最后的工具。
相反,您应该将生成临时表的查询直接集成到 CTE 中。为此,您可以只需复制/粘贴到子查询,如下所示:
with Total as (
select xyz...
from tables c
inner join (
select distinct acnt.account_value
from tablea a
join tableb b on b.account_key = a.account_key
outer apply fngetaccount(a.account_key) acnt
where b.period_end_dt >= '20170101'
group by acnt.identifier_value
) d on c.account_value = d.account_value
)
或者您可以将其用作另一个 CTE:
WITH k_temp_table as (
select distinct acnt.account_value
from tablea a
join tableb b on b.account_key = a.account_key
outer apply fngetaccount(a.account_key) acnt
where b.period_end_dt > 2016-12-31
group by acnt.identifier_value
)
, Total as (
select xyz...
from tables a
inner join k_temp_table k on c.account_value = a.account_value
)
其中任何一个都可能会执行得快得多,因为临时表不需要额外的 RAM,并且可以更好地利用源表上的索引进行 JOIN。
但是我们可以通过组合来自同一级别的两个查询的联接来做得更好。具体看起来是什么样子取决于您需要的列、事物的分组方式以及在将实际问题适应 Stack Overflow 问题时掩盖了多少内容。最终的结果是这样的:
with Total as (
select xyx...
from table a
join table b on b.account_key = a.account_key
outer apply fngetaccount(a.account_key) acnt
-- new join below for the table used in the CTE
inner join tables abc on abc.account_value = acnt.account_value
where b.period_end_dt >= '20170101'
group by acnt.identifier_value
)