或者也许有另一种选择。问题很简单:
我有这些信息(继续增加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 ()
,因此我只会获得最新的StartTime
和EndTime
对于每个MachID
/ DownCode
而不是每个单独的记录。
如果你看不到问题,这就是我想要的:
MachID DownCode StartTime EndTime
------------------------------------------------------------
PR01 ColorChg 1337713300 1337713303
PR01 ColorChg 1363254067 1363254075
PR01 ColorChg 1363259848 1363260292
...
请帮忙!我已经解决了这个问题,但它们没有UNPIVOT
那么快:
所以我想继续使用UNPIVOT
或同等的。
行的顺序在下面的注释中指定。
为了澄清任何有类似问题的人,答案是创建一个列,其中每一行都有唯一的值,因为PIVOT
总是在非透视列上执行隐式GROUP BY
。
只要一列完全唯一,这个隐式GROUP BY
基本上没有效果。
注意:我实际上没有查看执行计划,看看PIVOT
是否以这种方式正常工作,但在抽象中看来,这就是所选答案有效的原因。
答案 0 :(得分:8)
您不清楚如何将StartTime
和EndTime
相互关联,但您应该能够使用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;