Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server MSSQL 2005如何对这些数据进行分组_Sql Server_Sql Server 2005_Group By_Rank_Row Number - Fatal编程技术网

Sql server MSSQL 2005如何对这些数据进行分组

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

我在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-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