有一个报告,其查询在where子句中使用isnull,这会导致一些性能问题。 这是一个非常简单的例子。 http://www.sqlfiddle.com/#!6/79759/11
查询使用多值参数,通常只返回一个或两个值。 (我试图使用sqlfiddle中的表变量复制SSRS多值参数)
select
isnull(descrL,descr) as division,
product
from Upper
left join Lower on product = productL
where isnull(DescrL,Descr) in (@params)
有一个上级部门拥有所有产品。有些产品存在于儿童部门。如果它存在于较低的分区中,那就是应该显示的分区。
公司参数可以接受上级,下级或两者。
有关如何更改查询以获得更佳性能的任何想法?
答案 0 :(得分:2)
select descrL as division, product
from Lower
where DescrL like @params + '%'
union
Select descr, product
from Upper
where Descr like @params = '%'
这将是非常高效的。如果在顶部选择中找到匹配,则应在底部选择中对其进行抑制,因为它是联合而不是联合全部。请注意,而不是in。如果你执行in,那么就无法使用DescrL或Descr上的索引来查找结果。如果你这样做,索引就可以了。您可能必须调整应用程序逻辑才能使其工作。
如果你不能这样做,那就有这个解决方案。您必须将fn_split添加到您的数据库。 http://msdn.microsoft.com/en-us/library/aa496058(v=sql.80).aspx
select descrL as division, product
from Lower l
join dbo.fn_Split(@params, ',') p1
on l.DescrL = p1.value
union
Select descr, product
from Upper u
join dbo.fn_Split(@params, ',') p2
on u.Descr = p2.value
如果你真的想要完成性能的最后一点,你可以声明一个表变量,只运行fn_split一次以填充表变量,然后使两个连接成为表变量。所以在这里你也可以利用列上的索引,这是使查询更快的主要内容。当你运行它时,总是在sql server中“包含实际的执行计划”,并查看结果并确保你看到的是索引而不是表扫描。
编辑:我去了你的sqlfiddle链接。没有早点看到它。这有效。工会本身不会压制欺骗,因为你也选择了部门,对不起。因此,您必须使用not in或者我更喜欢左侧外部null。select descrL as division, productL as product
from Lower l
join @params p1
on l.DescrL = p1.division
union
Select u.descr, u.product
from Upper u
join @params p2
on u.Descr = p2.division
left join (select productL as product
from Lower l2
join @params p3
on l2.DescrL = p3.division) sub1
on u.product = sub1.product
where sub1.product is null
order by 2
答案 1 :(得分:1)
我不确定,但是在你的情况下会有效吗?
;with BothDivs as
(
select
isnull(descrL,descr) as division,
product
from Upper
left join Lower on product = productL
)
select division, product
from BothDivs
where division in (@params)