如何为PIVOT聚合指定GROUP BY

Kth*_*rog 4 sql t-sql sql-server 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
...
Run Code Online (Sandbox Code Playgroud)

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

我以这种方式转动数据:

SELECT * FROM
(
    SELECT *
    FROM cte_dl2
) Temp
PIVOT
(
    MAX(StartOrEnd)
    FOR StartTimeEndTime IN ([StartTime], [EndTime])
) Pvt
Run Code Online (Sandbox Code Playgroud)

哪个让我:

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
...
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到问题:它会自动GROUP BY对未指定的所有列进行操作PIVOT FOR IN (),因此我只获取最新的StartTimeEndTime每个MachID/ DownCode而不是每个单独的记录.

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

MachID  DownCode                StartTime   EndTime
------------------------------------------------------------
PR01    ColorChg                1337713300  1337713303
PR01    ColorChg                1363254067  1363254075
PR01    ColorChg                1363259848  1363260292
...
Run Code Online (Sandbox Code Playgroud)

请帮忙!我已经有办法解决这个问题,但它们并不像以下那样快UNPIVOT:

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

所以我想继续使用UNPIVOT或等效.

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


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

只要一列完全唯一,这隐含的GROUP BY基本上没有效果.

注意:我实际上没有看过执行计划,看看是否PIVOT按照这种方式工作,但在抽象中看起来,这就是所选答案有效的原因.

Tar*_*ryn 8

目前还不清楚你是如何将它们相互联系起来的StartTime,EndTime但你应该可以使用它row_number()来返回多个行的组合MachId,DownCode.这将创建另一个列,该列足够独特,可以在最终选择中返回多行:

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;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo.请注意,这假设您需要StartTimeEndTime基于StartOrEnd值,但表中的数据本身并不是有序的 - 如果您有一个可用于按特定顺序放置数据的列,则获取正确的顺序会更加容易.

如果你不想使用PIVOT它,可以使用聚合函数和CASE表达式来完成:

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;
Run Code Online (Sandbox Code Playgroud)

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

| MACHID | DOWNCODE |  STARTTIME |    ENDTIME |
|--------|----------|------------|------------|
|   PR01 | ColorChg | 1337713300 | 1337713303 |
|   PR01 | ColorChg | 1363254067 | 1363254075 |
|   PR01 | ColorChg | 1363259848 | 1363260292 |
Run Code Online (Sandbox Code Playgroud)

  • @KthProg好的,如果你觉得有必要继续这个关于大写与非大写的讨论,那就去聊聊吧.对于这个问题,这是偏离主题的. (2认同)