代码之家  ›  专栏  ›  技术社区  ›  bugfixr

优化SQL查询帮助

  •  2
  • bugfixr  · 技术社区  · 16 年前

    我们有一些我要优化的SQL代码。在代码中是一个运行起来相当昂贵的视图。为了这个问题,我们称之为“昂贵的观点”。在视图的顶部有一个通过两个子查询将视图连接到自身的查询。

    例如:

    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
    

    这是可行的,但很慢,因为我要从昂贵的观点中选择两次。我想做的是使用一个案例陈述,只从昂贵的观点中选择一次。

    例如:

    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)
    

    然后我可以将上面的结果分组,得到 几乎 与第一个查询相同:

    select sum(rank1IntCol), sum(rank2Intcol) 
    from ( *the above query* ) SubQueryData 
    group by someId
    

    问题是当等级为1时,我需要得到varcharcol1。我不能在组中使用它,因为当秩为1时,该列将包含不同的值,而当秩为2时则包含不同的值。

    是否有人有任何优化查询的解决方案,因此它只从昂贵的视图中选择一次,并且仍然能够获取varchar数据?

    事先谢谢。

    2 回复  |  直到 16 年前
        1
  •  3
  •   Quassnoi    16 年前

    很难猜测,因为我们看不到您的视图定义,请尝试以下操作:

    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 条件,所以这些技巧可能是多余的。

        2
  •  0
  •   Jens Schauder    16 年前
    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