Sql 如何为透视聚合指定分组依据
或者也许有另一种选择。问题其实很简单: 我有以下信息(更多行数为30万行): 这是一个称为“CTE_dl2”的CTE 我以这种方式旋转数据:Sql 如何为透视聚合指定分组依据,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,或者也许有另一种选择。问题其实很简单: 我有以下信息(更多行数为30万行): 这是一个称为“CTE_dl2”的CTE 我以这种方式旋转数据: SELECT * FROM ( SELECT * FROM cte_dl2 ) Temp PIVOT ( MAX(StartOrEnd) FOR StartTimeEndTime IN ([StartTime], [EndTime]) ) Pvt 这让我感到: MachID DownCode
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
...
您可以在这里看到问题:它会自动对in()的透视中未指定的所有列执行分组,因此我只获取每个MachID
/DownCode
的最新开始时间和结束时间
如果你看不出问题所在,以下是我想要了解的:
MachID DownCode StartTime EndTime
------------------------------------------------------------
PR01 ColorChg 1337713300 1337713303
PR01 ColorChg 1363254067 1363254075
PR01 ColorChg 1363259848 1363260292
...
请帮忙!我已经有办法解决这个问题,但它们没有UNPIVOT
那么快:
- 我的路线(未显示)=6s
- UNPIVOT=3s
因此,我想继续使用UNPIVOT
或等效工具
行的顺序在下面的注释中指定
为了向任何有类似问题的人澄清,答案是创建一列,其中每一行都有一个唯一的值,因为PIVOT
总是在非PIVOT列上执行隐式groupby
只要有一列是完全唯一的,这个隐式的groupby
基本上没有效果
注意:我实际上还没有查看执行计划,以查看PIVOT
是否正是以这种方式工作的,但从抽象上看,它似乎是,这就是为什么选择的答案是有效的。不清楚您如何将开始时间和结束时间相互关联,但是您应该能够使用行数()
返回多行MachId
,下代码的组合。这将创建另一列,该列的唯一性足以在最终选择中返回多行:
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;
看注意,这假设您希望开始时间
和结束时间
基于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;
看。您将在以下任一版本中获得相同的结果:
| MACHID | DOWNCODE | STARTTIME | ENDTIME |
|--------|----------|------------|------------|
| PR01 | ColorChg | 1337713300 | 1337713303 |
| PR01 | ColorChg | 1363254067 | 1363254075 |
| PR01 | ColorChg | 1363259848 | 1363260292 |
你怎么知道哪个EndTime
对应哪个StartTime
?如果它是由MachID、DownCode和StartOrEnd排序的,那么它总是下一个。是什么使一行成为“下一个”?表中没有自然顺序,有没有一个专栏我们可以用来排序结果?我讨厌粗鲁,但我只是说如果是MachID、DownCode、
和StartOrEnd的排序ed。一点也不粗鲁,我想念你的那部分comment@KthProg好的,如果你觉得有必要继续讨论CAP与非CAP的区别,那就去聊天吧。这是一个离题的问题。@bluefeet不,我想我们基本上已经解决了(尽管事实上,人们有他们自己的风格)。如果有这么多人坚持这种风格,那么可能CAPS
风格没有我想象中的好处,这两种方式都不会困扰我。@KthProg“不太管用”的意思是什么?小提琴中的结果正是你想要的结果。@Lamak-
我的错,我只是没有对结果进行排序,所以它看起来没有正常工作。它确实起了作用,非常感谢。我删除了评论。
| MACHID | DOWNCODE | STARTTIME | ENDTIME |
|--------|----------|------------|------------|
| PR01 | ColorChg | 1337713300 | 1337713303 |
| PR01 | ColorChg | 1363254067 | 1363254075 |
| PR01 | ColorChg | 1363259848 | 1363260292 |