我的以下查询运行得很慢:
SELECT
DISTINCT a.Role as Role
FROM
[Table_A] a
JOIN
[Table_B] b ON (a.Key = b.Key)
WHERE
b.Date BETWEEN @StartDate AND @EndDate
AND ISNULL(a.ID, -1) IN (@People)
变量@StartDate
和@EndDate
和@People
的值来自SSRS报告中的参数。日期参数只是日期。 @People
参数是一个多值参数。
问题是@People
包含3000多个值。因此,查询必须使用IN
子句来遍历。在SSRS中运行查询时,这确实会减慢查询速度。
我想用一个现存子句代替IN
子句,但在这种情况下我似乎无法使它起作用。我需要以某种方式从@People
子句中的EXISTS
变量中选择值,并将其重新连接到第一个表,但是我什至不知道这是否可行。
在这种情况下,尝试使用EXISTS
可能使我走错了方向。但是我仍然需要修复查询,以便它运行得更快。
任何人都可以帮忙吗?
答案 0 :(得分:1)
select
r.acctnbr,
r.modnbr,
r.modtypcd,
r.moddate,
u.userfieldcd,
case when modnbr = max(r.modnbr ) over (partition by r.acctnbr)
then u.value else null end as value
from loanrestructuretracking r
LEFT JOIN acctuserfield u on u.acctnbr = r.acctnbr
and u.userfieldcd = 'LOMO'
将使查询不可SARG。您最好使用ISNULL(a.ID, -1)
,但是,带有这么多参数的(a.ID IN (@People) OR a.ID IS NULL)
不太可能很好地运行。
我在这里运行内存(我在家中没有SSRS),但是如果我记得SSRS使用多值参数和IN
做一些“魔术”,那么扩展性就不好。也许您最好尝试使用IN
和分隔符(例如DelimitedSplit8k
)。此特定示例依赖于EXISTS
少于8000个字符。
@People
但是,考虑到这里的顺序位置无关紧要,则可以使用其他拆分器。例如XML Splitter。
为完整起见,快速编写了XML Splitter函数:
SELECT DISTINCT a.Role
FROM [Table_A] a
JOIN [Table_B] b ON a.Key = b.Key
WHERE b.Date BETWEEN @StartDate AND @EndDate
AND (EXISTS (SELECT 1
FROM dbo.DelimitedSplit8K(@People,',') DS
WHERE DS.Item = a.ID)
OR a.ID IS NULL);
添加了不带功能的完整示例:
CREATE FUNCTION dbo.XMLSplitter (@DelimitedString varchar(MAX))
RETURNS TABLE AS RETURN
SELECT n.d.value('.','varchar(MAX)') AS Item
FROM (VALUES(CONVERT(xml,'<d>'+ REPLACE(@DelimitedString,',','</d><d>') + '</d>'))) V(X)
CROSS APPLY V.X.nodes('d') n(d);
GO