优化sql查询的帮助

时间:2009-08-17 14:49:51

标签: sql sql-server

我们正在尝试优化一些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数据?

提前致谢。

2 个答案:

答案 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