我们正在尝试优化一些SQL代码。在代码中是一个运行起来相当昂贵的视图。为了这个问题,我们称之为ExpensiveView。在视图的顶部有一个查询,它通过两个子查询将视图连接到自身。
例如:
select v1.varCharCol1, v1.intCol, v2.intCol from (
select someId, varCharCol1, intCol from ExpensiveView where rank=1
) as v1 inner join (
select someId, intCol from ExpensiveView where rank=2
) as v2 on v1.someId = v2.someId
示例结果集:
some random string, 5, 10
other random string, 15, 15
这样可行,但由于我不得不从ExpensiveView中选择两次,因此速度很慢。我想做的是使用case语句只从ExpensiveView中选择一次。
例如:
select someId,
case when rank = 1 then intCol else 0 end as rank1IntCol,
case when rank = 2 then intCol else 0 end as rank2IntCol
from ExpensiveView where rank in (1,2)
然后,我可以通过someId将上述结果分组,并使几乎与第一个查询相同:
select sum(rank1IntCol), sum(rank2Intcol)
from ( *the above query* ) SubQueryData
group by someId
问题是当秩为1时我需要得到的varCharCol1。我不能在组中使用它,因为当列为1时,该列将包含与秩为2时不同的值。
有没有人有任何优化查询的解决方案,所以它只从ExpensiveView中选择一次,仍然可以获取varchar数据?
提前致谢。
答案 0 :(得分:3)
很难猜到,因为我们没有看到你的视图定义,但试试这个:
SELECT MIN(CASE rank WHEN 1 THEN v1.varCharCol1 ELSE NULL END),
SUM(CASE rank WHEN 1 THEN rank1IntCol ELSE 0 END),
SUM(CASE rank WHEN 2 THEN rank2IntCol ELSE 0 END)
FROM query
GROUP BY
someId
请注意,在大多数情况下,对于这样的查询:
SELECT *
FROM mytable1 m1
JOIN mytable1 m2
ON …
SQL Server
优化器只会构建一个Eager Spool
(临时索引),稍后将用于搜索JOIN
条件,因此这些技巧可能是多余的。
答案 1 :(得分:0)
select someId,
case when rank = 1 then varCharCol1 else '_' as varCharCol1
case when rank = 1 then intCol else 0 end as rank1IntCol,
case when rank = 2 then intCol else 0 end as rank2IntCol
from ExpensiveView where rank in (1,2)
然后在封闭查询中使用min()或max