如何为PIVOT聚合指定GROUP BY

时间:2014-10-13 17:19:17

标签: sql sql-server tsql pivot

或者也许有另一种选择。问题很简单:

我有这些信息(继续增加300k行):

MachID  DownCode                StartOrEnd  StartTimeEndTime
------------------------------------------------------------
PR01    ColorChg                1337713300  StartTime
PR01    ColorChg                1337713303  EndTime
PR01    ColorChg                1363254067  StartTime
PR01    ColorChg                1363254075  EndTime
PR01    ColorChg                1363259848  StartTime
PR01    ColorChg                1363260292  EndTime
...

这是一个名为'cte_dl2'的CTE。

我以这种方式转动数据:

SELECT * FROM
(
    SELECT *
    FROM cte_dl2
) Temp
PIVOT
(
    MAX(StartOrEnd)
    FOR StartTimeEndTime IN ([StartTime], [EndTime])
) Pvt

哪个让我:

MachID  DownCode                StartTime   EndTime
------------------------------------------------------
PR01    ColorChg                1375207208  1375207316
PR01    COMP                    1412124847  1412131608
PR01    DIE SET                 1408502593  1408502595
PR01    DieStart                1397704258  1397704381
PR01    FeedLoad                1375099369  1375099506
...

您可以在此处查看问题:它会自动对GROUP BY中未指定的所有列执行PIVOT FOR IN (),因此我只会获得最新的StartTimeEndTime对于每个MachID / DownCode而不是每个单独的记录。

如果你看不到问题,这就是我想要的:

MachID  DownCode                StartTime   EndTime
------------------------------------------------------------
PR01    ColorChg                1337713300  1337713303
PR01    ColorChg                1363254067  1363254075
PR01    ColorChg                1363259848  1363260292
...

请帮忙!我已经解决了这个问题,但它们没有UNPIVOT那么快:

  • 我的方式(未显示)= 6s
  • UNPIVOT = 3s

所以我想继续使用UNPIVOT或同等的。

行的顺序在下面的注释中指定。


为了澄清任何有类似问题的人,答案是创建一个列,其中每一行都有唯一的值,因为PIVOT总是在非透视列上执行隐式GROUP BY

只要一列完全唯一,这个隐式GROUP BY基本上没有效果。

注意:我实际上没有查看执行计划,看看PIVOT是否以这种方式正常工作,但在抽象中看来,这就是所选答案有效的原因。

1 个答案:

答案 0 :(得分:8)

您不清楚如何将StartTimeEndTime相互关联,但您应该能够使用row_number()返回{{1}的多个行组合},MachId。这将创建另一个列,该列足够独特,可以在最终选择中返回多行:

DownCode

SQL Fiddle with Demo注意,这假定您希望select machid, downcode, StartTime, EndTime from ( select machid, downcode, startorend, starttimeendtime, rn = row_number() over(partition by machid, downcode, StartTimeEndTime order by startorend) from cte_dl2 ) d pivot ( max(startorend) for starttimeendtime in (StartTime, EndTime) ) piv; StartTime基于EndTime值,但表格中的数据并非本身有序 - 这将更加容易如果您有一个可用于按特定顺序放置数据的列,则获取正确的订单。

如果您不想使用StartOrEnd,可以使用聚合函数和PIVOT表达式来完成此操作:

CASE

SQL Fiddle with Demo。任何一个版本都会得到相同的结果:

select 
  machid,
  downcode,
  StartTime = max(case when starttimeendtime = 'StartTime' then startorend else null end),
  EndTime = max(case when starttimeendtime = 'EndTime' then startorend else null end) 
from
(
  select machid,
    downcode,
    startorend,
    starttimeendtime,
    rn = row_number() over(partition by machid, downcode, StartTimeEndTime
                            order by startorend) 
  from cte_dl2
) d
group by machid, downcode, rn;