【问题标题】:SQL Server 2008 R2: Dynamic Pivot table query performanceSQL Server 2008 R2:动态数据透视表查询性能
【发布时间】:2014-11-24 12:32:48
【问题描述】:

我有下表的记录:

示例

表名:测试

 cola   colb  colc
-------------------
 111    222   A1
 111    333   A2
 111    344   A3
 111    444   A4
 5443   555   B1
 767    222   A1
 767    333   A2
 767    344   A3
 8998   222   A1
 8998   333   A2

我想用这些数据做什么:我想用一些特定的 colc 值显示数据透视表,这些值仅属于 cola 值而不属于其他值。例如,在下面的脚本中,A1,A2,A3 属于 767 并不多或少。

注意:下面的脚本可以很好地处理预期的结果但是问题在于查询性能,因为我多次加入同一个表,该表有数百万导致我等待很长时间循环的记录。

数据透视表脚本

Declare @sql varchar(max)
Declare @stuff varchar(max) = 'A1,A2,A3'

SET @sql = 'SELECT cola,Available,'+@Stff+'
           FROM                     
           (
                SELECT  v.cola,v.colc,c.Available
                FROM tft AS v   
                inner join
                (
                   select cola,count(distinct colc) AS Available
                   FROM tft a
                   where colc in ('+@stuff+')
                   group by cola
                   having(select count(DISTINCT colc) 
                   from tft b where b.cola= a.cola and colc in('+@stuff+'))= 3
                   and (select count(DISTINCT colc) from tft c where c.cola = a.cola) = 3
                ) c 
                on c.cola = v.cola
           ) p                     
           PIVOT                
           (            
                count(colc)                        
                FOR colc IN ('+@stuff+')                        
           ) AS pvt';   

print(@sql);
exec(@sql);

问题:问题在于大量记录会导致长时间延迟。有没有更好的方法来编写相同的概念?

【问题讨论】:

  • 开始杀死不同的人。这些可能会花费您的时间。然后继续发布查询计划。
  • @TomTom,如果我这样做,那么我将无法获得结果。 :(
  • @TomTom,因为我想在having子句中计算不同的colc
  • 那么你就被卡住了——尤其是当你对查询计划的请求越来越多时。Distinct 是相当邪恶的。摆脱它。哎呀, GROUP BY 可以轻松替换它。请查询计划。

标签: sql-server sql-server-2008-r2 pivot


【解决方案1】:

这是另一种方式,它避免了DISTINCTs 并使用 sum 而不是 pivot 函数:

SELECT  orig.cola ,
        colas.counter ,
        SUM(CASE orig.colc WHEN 'A1' THEN 1 ELSE 0 END) AS A1 ,
        SUM(CASE orig.colc WHEN 'A2' THEN 1 ELSE 0 END) AS A2 ,
        SUM(CASE orig.colc WHEN 'A3' THEN 1 ELSE 0 END) AS A3
FROM    tft orig
        INNER JOIN ( SELECT cola ,
                            COUNT(1) AS counter
                     FROM   ( SELECT    cola ,
                                        colc
                              FROM      tft 
                              WHERE     cola NOT IN (
                                        SELECT  cola
                                        FROM    tft 
                                        WHERE   colc NOT IN ( 'A1', 'A2', 'A3' ) )
                              GROUP BY  cola ,
                                        colc
                            ) a
                     GROUP BY cola
                     HAVING COUNT(1) > 2
                   ) colas ON colas.cola = orig.cola
GROUP BY orig.cola ,
        colas.counter

我已经对其进行了测试,它使用您的示例数据返回与您的查询相同的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多