我在SQL SERVER 2005中有一个这样的表
No WorkOrder StartDateTime EndDateTime
======================================================
1 WO111111 2019-01-01 07:00 2019-01-01 08:00
2 WO111111 2019-01-01 08:00 2019-01-01 08:30
3 WO222222 2019-01-01 08:30 2019-01-01 09:30
4 WO222222 2019-01-01 09:30 2019-01-01 10:00
6 WO222222 2019-01-01 10:00 2019-01-01 12:00
7 WO111111 2019-01-01 12:00 2019-01-01 17:00
如何获取下表
WorkOrder StartDateTime EndDateTime
============================================
WO111111 2019-01-01 07:00 2019-01-01 08:30
WO222222 2019-01-01 08:30 2019-01-01 12:00
WO111111 2019-01-01 12:00 2019-01-01 17:00
我尝试了row_number()和rank(),但没有用。
DECLARE @Tmp TABLE (No int, WorkOrder varchar(20), StartDateTime datetime, EndDateTime datetime)
insert into @Tmp values(1,'WO111111','2019-01-01 07:00','2019-01-01 08:00')
insert into @Tmp values(2,'WO111111','2019-01-01 08:00','2019-01-01 08:30')
insert into @Tmp values(3,'WO222222','2019-01-01 08:30','2019-01-01 09:30')
insert into @Tmp values(4,'WO222222','2019-01-01 09:30','2019-01-01 10:00')
insert into @Tmp values(5,'WO222222','2019-01-01 10:00','2019-01-01 12:00')
insert into @Tmp values(6,'WO111111','2019-01-01 12:00','2019-01-01 17:00')
select * from @Tmp;
select g,WorkOrder,min(StartDateTime)StartDateTime,Max(EndDateTime)EndDateTime
From(
select rank()over(order by WorkOrder)as g,* from @Tmp
)a group by g,WorkOrder
答案 0 :(得分:0)
您可以通过自连接和SUM
窗口功能来摆脱困境。首先通过考虑WorkOrder
的顺序来确定No
值何时可以分组,然后再用MIN
和MAX
分组以粉碎日期间隔。 / p>
;WITH LaggedWorkOrder AS
(
SELECT
T1.WorkOrder,
T1.StartDateTime,
T1.EndDateTime,
T1.No,
WorkOrderChange = CASE
WHEN T2.WorkOrder = T1.WorkOrder THEN 0
ELSE 1 END
FROM
@Tmp AS T1
LEFT JOIN @Tmp AS T2 ON T1.No - 1 = T2.No
),
WorkOrderGroups AS
(
SELECT
L.WorkOrder,
L.StartDateTime,
L.EndDateTime,
L.No,
WorkOrderGroup = SUM(L.WorkOrderChange) OVER (ORDER BY L.No ASC)
FROM
LaggedWorkOrder AS L
)
SELECT
W.WorkOrder,
StartDateTime = MIN(W.StartDateTime),
EndDateTime = MAX(W.EndDateTime)
FROM
WorkOrderGroups AS W
GROUP BY
W.WorkOrderGroup,
W.WorkOrder
ORDER BY
W.WorkOrderGroup
结果:
WorkOrder StartDateTime EndDateTime
WO111111 2019-01-01 07:00:00.000 2019-01-01 08:30:00.000
WO222222 2019-01-01 08:30:00.000 2019-01-01 12:00:00.000
WO111111 2019-01-01 12:00:00.000 2019-01-01 17:00:00.000
中间的CTE结果如下:
滞后工作订单(请参阅每当工作订单更改值时):
WorkOrder StartDateTime EndDateTime No WorkOrderChange
WO111111 2019-01-01 07:00:00.000 2019-01-01 08:00:00.000 1 1
WO111111 2019-01-01 08:00:00.000 2019-01-01 08:30:00.000 2 0
WO222222 2019-01-01 08:30:00.000 2019-01-01 09:30:00.000 3 1
WO222222 2019-01-01 09:30:00.000 2019-01-01 10:00:00.000 4 0
WO222222 2019-01-01 10:00:00.000 2019-01-01 12:00:00.000 5 0
WO111111 2019-01-01 12:00:00.000 2019-01-01 17:00:00.000 6 1
WorkOrderGroups (生成MAX / MIN的分组值):
WorkOrder StartDateTime EndDateTime No WorkOrderGroup
WO111111 2019-01-01 07:00:00.000 2019-01-01 08:00:00.000 1 1
WO111111 2019-01-01 08:00:00.000 2019-01-01 08:30:00.000 2 1
WO222222 2019-01-01 08:30:00.000 2019-01-01 09:30:00.000 3 2
WO222222 2019-01-01 09:30:00.000 2019-01-01 10:00:00.000 4 2
WO222222 2019-01-01 10:00:00.000 2019-01-01 12:00:00.000 5 2
WO111111 2019-01-01 12:00:00.000 2019-01-01 17:00:00.000 6 3
PD::请考虑升级服务器版本,2005年终止于2016年4月。
答案 1 :(得分:0)
现在知道您正在使用SQL Server 2005,您将需要依靠
outer apply
进行此处要求的任意联接以确定相对的先前记录。
您尚未在此处概述谓词。但是从输出中猜测,您正在寻找每个组的第一个WorkOrder
,在这种情况下,这似乎要经过一段时间才能出现一个不同的WorkOrder
。
下面的方法使用apply
通过top 1
获取先前的记录,特别是outer apply
以确保我们不会丢失第一条记录(将其视为{{1} }。
left join
迭代器几乎总是被忽略并且经常被遗忘。但是,当您需要迭代而又没有像键这样的具体连接谓词时,它是一个非常功能强大的工具。我在大表上使用了这种方法来解决“前n个问题”,发现有时它的性能要比内置函数好。
请注意,我已选择apply
作为平手。
No
答案 2 :(得分:-1)
使用最小,最大分组来获得预期的输出
SELECT WorkOrder, min(StartDateTime),max(EndDateTime) FROM `tb` group by WorkOrder
输出
==============
WO111111 2019-01-01 07:00 2019-01-01 08:30
WO222222 2019-01-01 08:30 2019-01-01 12:00
WO111111 2019-01-01 12:00 2019-01-01 17:00