【问题标题】:how to optimize my sql query如何优化我的 sql 查询
【发布时间】:2011-09-22 04:00:10
【问题描述】:

我想优化我之前编写的 sql 查询(请参阅下面附加的 sql 查询)。这个查询很直接而且非常简单,但是需要修改它,因为它在性能测试中失败了,而且我知道查询很慢。我的团队负责人确实向我提到在查询中使用“Pivoting”,但我没有理解他的观点如何进行旋转。请有人在这方面帮助我。

Declare @tempTable Table(
DataSourceColumID int, fDataSourceID int, seqNum int, ColName varchar(50), HeaderName varchar(50)
)
Insert into @tempTable 
(DataSourceColumID, fDataSourceID,seqNum, ColName,HeaderName) 
Select 101,1,2,'col1', 'column 1'
Union ALL
Select 102,1,1,'col2', 'column 2'
Union All
Select 103,1,3,'col6', 'column 6'
Union All
Select 104,1,4,'col50', 'column 50'
select * From @tempTable 

Declare @ColumnOrderTable table (col_A varchar(10),col_B varchar(10),col_C varchar(10),col_D varchar(10),col_E varchar(10),col_F varchar(10),col_G varchar(10))
Insert into @ColumnOrderTable (col_A ,col_B ,col_C ,col_D ,col_E ,col_F ,col_G )
select 
Case When seqNum=1 then HeaderName else '' end as col_A,
Case When seqNum=2 then HeaderName else '' end as col_B ,
Case When seqNum=3 then HeaderName else '' end as col_C ,
Case When seqNum=4 then HeaderName else '' end as col_D ,
Case When seqNum=5 then HeaderName else '' end as col_E ,
Case When seqNum=6 then HeaderName else '' end as col_F, 
Case When seqNum=7 then HeaderName else '' end as col_G
from @tempTable

select max(col_A) as col_A ,max(col_B) col_B,max(col_C) col_C,max(col_D) col_D,max(col_E) col_E,max(col_F) col_F,max(col_G) col_G  From @ColumnOrderTable 

【问题讨论】:

标签: sql sql-server sql-server-2005 tsql reportingservices-2005


【解决方案1】:

您可以省略该步骤并使用子选择,而不是选择到 @ColumnOrderTable。

简化的原始语句

SELECT  MAX(col_A)
        , MAX(col_B)
        , MAX(col_C)
        , MAX(col_D)
        , MAX(col_E)
        , MAX(col_F)
        , MAX(col_G)
FROM    (
          SELECT
            Case When seqNum=1 then HeaderName else '' end as col_A,
            Case When seqNum=2 then HeaderName else '' end as col_B ,
            Case When seqNum=3 then HeaderName else '' end as col_C ,
            Case When seqNum=4 then HeaderName else '' end as col_D ,
            Case When seqNum=5 then HeaderName else '' end as col_E ,
            Case When seqNum=6 then HeaderName else '' end as col_F, 
            Case When seqNum=7 then HeaderName else '' end as col_G
          FROM  @tempTable
        ) t

可以通过使用PIVOT 函数转换此语句来省略子选择本身。

使用 PIVOT

SELECT  col_A = [1]
        , col_B = [2]
        , col_C = [3]
        , col_D = [4]
        , col_E = [5] 
        , col_F = [6]
        , col_G = [7]
FROM    (SELECT seqNum, HeaderName FROM @tempTable) t
PIVOT   (MAX(HeaderName) FOR seqNum IN ([1], [2], [3], [4], [5], [6], [7])) pt  

【讨论】:

    【解决方案2】:

    你的方法在很多方面都很糟糕:

    • 首先您选择一个临时表。这意味着必须在第二步停止之前复制所有数据。
    • 然后你再次复制到另一个临时表中
    • 然后你终于做到了。

    这是一个初学者nonono。

    • 消除两个临时表。只是摆脱他们。即使不使用枢轴或其他东西,也根本不需要这样做。您可以直接在通过 SQL 时选择 (max)。临时表很糟糕,因为它们意味着必须首先处理所有数据 - 在您的情况下,您处理所有数据三次。优化器无法将其优化掉。

    其次,检查枢轴。有文档 ;) 查一下,然后提出具体问题。

    【讨论】:

    • 我假设 OP 只使用一个 temptable。另一个是为了我们的利益提供一个可运行的脚本(一件好事)。
    • 所以他仍然可以将他的运行时间缩短多少 - 99%?由于没有过滤条件,这取决于他将多少数据不必要地处理到临时表中。
    • 嗨 Lieven,非常感谢您提供的查询,现在我了解了如何使用 PIVOT 并且它可以根据需要正确获取详细信息。你是对的,我只是为了理解目的而创建了一个临时表——只是为了插入一些值并对其进行测试。非常感谢您这么快给我答复。
    • @desi - 不要提及它,但您已将评论附加到错误的答案:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多