Sql server MSSQL 2005如何对这些数据进行分组
我在SQLServer2005中有这样一个表Sql server MSSQL 2005如何对这些数据进行分组,sql-server,sql-server-2005,group-by,rank,row-number,Sql Server,Sql Server 2005,Group By,Rank,Row Number,我在SQLServer2005中有这样一个表 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-0
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
我试过排号和排名,但没用
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
您可以使用自联接和求和窗口函数。首先确定WorkOrder值何时更改,以便能够通过考虑No的顺序进行分组,然后仅使用MIN和MAX进行分组,以粉碎日期间隔
;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结果如下所示:
LaggedWorkOrder在WorkOrder更改值时查看:
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
WorkOrderGroup为最大/最小值生成分组值:
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月。 现在知道您使用的是SQL Server 2005,您需要依靠外部应用程序来进行此处所需的任意连接,以确定相对的先前记录
你还没有在这里概述这个断言。但是从输出中猜测,您正在查找每个组的第一个工作顺序,在本例中,这似乎是一次运行,直到出现不同的工作顺序 下面的方法使用apply来获取使用top 1的前一条记录,特别是外部apply,以确保我们不会丢失第一条记录—将其视为左连接 apply迭代器几乎总是被忽略和遗忘。但是,当您需要迭代而不需要像键这样的具体连接谓词时,它是一个非常强大的工具。我在大型表上使用了这种方法来解决前n个问题,发现它有时比内置的性能更好 请注意,我选择了“否”作为打破僵局的条件 使用group by min、max获取预期输出 输出 ============== 工作订单开始日期时间结束日期时间你能告诉我们你的排号和排名尝试吗?你能告诉我们到目前为止你都尝试了什么吗?排号在这里帮不了你。您需要延迟。一个非常常见的问题-@rxyes已修复,请立即尝试。顺序是否错误?此行=>WorkOrderGroup=SUML.WorkOrderChange超过订单的L.编号ASC@rxyes就我对你期望结果的理解而言,顺序是可以的,如果你能详细解释一下你想要的结果,我可以相应地更新答案。sql server 2005不支持sumover。我不能在sql server中使用lag2005@rxyes将我的答案调整为使用外部应用。直到你的问题更新后,我才意识到你的版本限制。
CREATE TABLE #WorkOrders (
No INT IDENTITY PRIMARY KEY
,WorkOrder VARCHAR(8) NOT NULL
,StartDateTime DATETIME NOT NULL
,EndDateTime DATETIME NOT NULL);
INSERT INTO #WorkOrders (WorkOrder, StartDateTime, EndDateTime)
VALUES ('WO111111','20190101 07:00','20190101 08:00')
,('WO111111','20190101 08:00','20190101 08:30')
,('WO111111','20190101 08:30','20190101 09:30')
,('WO222222','20190101 08:30','20190101 09:30')
,('WO222222','20190101 09:30','20190101 10:00')
,('WO222222','20190101 10:00','20190101 12:30')
,('WO111111','20190101 12:00','20190101 12:30')
SELECT wo.WorkOrder
, wo.StartDateTime
, wo.EndDateTime
FROM #WorkOrders AS wo
OUTER APPLY (
SELECT TOP(1)
*
FROM #WorkOrders AS wo2
WHERE wo2.StartDateTime < wo.StartDateTime
ORDER BY wo2.StartDateTime DESC, No DESC
) AS prev
WHERE prev.WorkOrder IS NULL
OR prev.WorkOrder <> wo.WorkOrder
DROP TABLE #WorkOrders;
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