【问题标题】:TSQL - Partition BY if in orderTSQL - 按顺序分区
【发布时间】:2017-01-14 06:30:57
【问题描述】:

在按 [Status_DateTime] DESC 排序后,我尝试按 [Status] 进行分区。 因此,只有连续的 [Status] 才会被分区,以便为其获取最早的 Date。

/****** Object:  Table [dbo].[Order_Status]    Script Date: 1/13/2017 1:06:38 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Order_Status](
    [Case_No_ID] [int] NULL,
    [Status] [nvarchar](60) NULL,
    [Status_Datetime] [datetime] NULL,
    [Employee_ID] [int] NULL
) ON [PRIMARY]

GO
INSERT [dbo].[Order_Status] ([Case_No_ID], [Status], [Status_Datetime], [Employee_ID]) VALUES     
(223079, N'HP - HOLD FOR PARTS', CAST(N'2015-12-21T16:44:50.000' AS DateTime), 740)
,(223079, N'DP - ORDER CREATED', CAST(N'2015-12-21T16:45:11.000' AS DateTime), 740)
,(223079, N'PP - PRINT PL', CAST(N'2015-12-21T16:47:03.000' AS DateTime), 709)
,(223079, N'PS- PARTS SHIPPED', CAST(N'2015-12-21T17:50:39.000' AS DateTime), 824)
,(223079, N'OS - MACHINE RECEIVED', CAST(N'2015-12-29T09:47:34.000' AS DateTime), 2)
,(223079, N'RP - UNDER INSPECTION', CAST(N'2015-12-30T12:14:07.000' AS DateTime), 168)
,(223079, N'RP - UNDER INSPECTION', CAST(N'2015-12-30T13:41:01.000' AS DateTime), 168)
,(223079, N'RP - UNDER INSPECTION', CAST(N'2016-01-05T14:15:46.000' AS DateTime), 241)
,(223079, N'RP - UNDER INSPECTION', CAST(N'2016-01-06T13:44:18.000' AS DateTime), 13)
,(223079, N'HP - HOLD FOR PARTS', CAST(N'2016-01-07T14:18:59.000' AS DateTime), 710)
,(223079, N'RELEASED FROM HOLD FOR PART', CAST(N'2016-01-11T16:37:49.000' AS DateTime), 710)
,(223079, N'RP - UNDER INSPECTION', CAST(N'2016-01-12T08:58:05.000' AS DateTime), 241)
,(223079, N'HP - HOLD FOR PARTS', CAST(N'2016-01-20T09:50:19.000' AS DateTime), 710)
,(223079, N'HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI', CAST(N'2016-01-25T15:32:19.000' AS DateTime), 755)
,(223079, N'HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI', CAST(N'2016-03-04T15:56:52.000' AS DateTime), 755)
,(223079, N'HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI', CAST(N'2016-05-16T14:57:12.000' AS DateTime), 755)
,(223079, N'HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI', CAST(N'2016-06-14T15:35:14.000' AS DateTime), 755)
,(223079, N'HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI', CAST(N'2016-08-15T15:28:32.000' AS DateTime), 755)
GO

更新: 如何在 Partition BY 之前使用 Order BY? 如果某个状态在连续 2 行中重复,我正在尝试获取第一个日期时间,如果状态没有改变但 Status_DateTime 改变了。

例如:

Case_No_ID  Status                                                                                               Status_DateTime         First_Time              Employee_ID
----------- ---------------------------------------------------------------------------------------------------- ----------------------- ----------------------- -----------
223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-08-15 15:28:32.000 2016-01-25 15:32:19.000 755
223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-06-14 15:35:14.000 2016-01-25 15:32:19.000 755
223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-05-16 14:57:12.000 2016-01-25 15:32:19.000 755
223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-03-04 15:56:52.000 2016-01-25 15:32:19.000 755
223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-01-25 15:32:19.000 2016-01-25 15:32:19.000 755

不影响那些不在一行中的,例如:下面的'HP - HOLD FOR PARTS'

Case_No_ID  Status                                                                                               Status_DateTime         First_Time              Employee_ID
----------- ---------------------------------------------------------------------------------------------------- ----------------------- ----------------------- -----------
    223079      HP - HOLD FOR PARTS                                                                                  2016-01-20 09:50:19.000 2016-01-20 09:50:19.000 710
    223079      RP - UNDER INSPECTION                                                                                2016-01-12 08:58:05.000 2016-01-12 08:58:05.000 241
    223079      RELEASED FROM HOLD FOR PART                                                                          2016-01-11 16:37:49.000 2016-01-11 16:37:49.000 710
    223079      HP - HOLD FOR PARTS                                                                                  2016-01-07 14:18:59.000 2016-01-07 14:18:59.000 710
    223079      RP - UNDER INSPECTION                                                                                2016-01-06 13:44:18.000 2016-01-06 13:44:18.000 13

我尝试了以下方法:

Select 
    ROW_NUMBER() Over (order by status_Datetime Desc) rownum
    , Case_No_ID
    , Status
    , Status_DateTime 
    , First_value(Status_DateTime) over (partition by [status] Order by [status] Desc) First_Time
    , Employee_ID
from Order_Status
where Case_No_ID = 223079
order by Status_DateTime desc

如果状态更改是连续顺序(第 1 到 5 行),它工作正常,第一次进入状态是 '2016-01-25 15:32:19.000',因为状态没有改变,但是如果您检查第 6 行的 First_Time 列,它会显示第 9 行的 Status_DateTime,但它们之间的状态发生了变化。

rownum               Case_No_ID  Status                                                                                               Status_DateTime         First_Time              Employee_ID
-------------------- ----------- ---------------------------------------------------------------------------------------------------- ----------------------- ----------------------- -----------
1                    223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-08-15 15:28:32.000 2016-08-15 15:28:32.000 755
2                    223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-06-14 15:35:14.000 2016-08-15 15:28:32.000 755
3                    223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-05-16 14:57:12.000 2016-08-15 15:28:32.000 755
4                    223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-03-04 15:56:52.000 2016-08-15 15:28:32.000 755
5                    223079      HP06 - PARTS SHORTAGE, PLANNER CONFIRM ETA AND TRIGGER EDI                                           2016-01-25 15:32:19.000 2016-08-15 15:28:32.000 755
6                    223079      HP - HOLD FOR PARTS                                                                                  2016-01-20 09:50:19.000 2015-12-21 16:44:50.000 710
7                    223079      RP - UNDER INSPECTION                                                                                2016-01-12 08:58:05.000 2016-01-12 08:58:05.000 241
8                    223079      RELEASED FROM HOLD FOR PART                                                                          2016-01-11 16:37:49.000 2016-01-11 16:37:49.000 710
9                    223079      HP - HOLD FOR PARTS                                                                                  2016-01-07 14:18:59.000 2015-12-21 16:44:50.000 710
10                   223079      RP - UNDER INSPECTION                                                                                2016-01-06 13:44:18.000 2016-01-12 08:58:05.000 13
11                   223079      RP - UNDER INSPECTION                                                                                2016-01-05 14:15:46.000 2016-01-12 08:58:05.000 241
12                   223079      RP - UNDER INSPECTION                                                                                2015-12-30 13:41:01.000 2016-01-12 08:58:05.000 168
13                   223079      RP - UNDER INSPECTION                                                                                2015-12-30 12:14:07.000 2016-01-12 08:58:05.000 168
14                   223079      OS - MACHINE RECEIVED                                                                                2015-12-29 09:47:34.000 2015-12-29 09:47:34.000 2
15                   223079      PS- PARTS SHIPPED                                                                                    2015-12-21 17:50:39.000 2015-12-21 17:50:39.000 824
16                   223079      PP - PRINT PL                                                                                        2015-12-21 16:47:03.000 2015-12-21 16:47:03.000 709
17                   223079      DP - ORDER CREATED                                                                                   2015-12-21 16:45:11.000 2015-12-21 16:45:11.000 740
18                   223079      HP - HOLD FOR PARTS                                                                                  2015-12-21 16:44:50.000 2015-12-21 16:44:50.000 740

感谢您的帮助

【问题讨论】:

  • 我投票结束这个问题,因为它提出了一个目标,但缺少一个问题。它也没有任何研究迹象或达到目标的尝试。
  • 我没有遵循你想要的。最后两个结果样本没有多大意义。
  • 指定问题。
  • 什么版本的 SQL Server?
  • @HABO,目标等同于问题。这是如何实现目标的。无论如何,我更新了我的帖子。研究的指示是帖子本身,因为我们应该在发布之前进行研究。无论如何,我也添加了我尝试过的内容。

标签: sql sql-server database tsql


【解决方案1】:

如果我理解正确,你需要这样的东西。这使用running total over lag将连续状态分组到同一组,然后使用first_value分区:

select case_no_id, status, status_datetime, first_value(status_datetime) over (partition by GRP order by status_datetime desc), employee_id
from ( 
    select sum(case when Status = prev_status then 0 else 1 end) over (order by Status_datetime desc) as GRP, * 
    from (
        select *, lag(status) over (order by Status_Datetime desc) as prev_status from Order_Status 
    ) X
) Y
order by Status_Datetime desc

你在rextester中的例子

【讨论】:

  • 非常接近,但是对于您在 restester 上提供的示例,它显示的是该状态的最后一个日期时间,而不是第一个。 (在第 1 行,日期应从第 5 行开始)
  • 如果我在 FIRST_VALUE 中将 DESC 更改为 ASC,效果很好! select case_no_id, status, status_datetime, first_value(status_datetime) over (partition by GRP order by status_datetime ASC), employee_id from (select sum(case when Status = prev_status then 0 else 1 end) over (order by Status_datetime desc) as GRP, * from (select *, lag(status) over (order by Status_Datetime desc) as prev_status from Order_Status) X ) Y order by Status_Datetime desc
【解决方案2】:

一种方法只是使用lag() 来查看之前的状态并仅保留已更改的状态:

select os.*
from (select os.*,
             lag(status) over (partition by Case_No_ID order by Status_Datetime) as prev_status
      from Order_Status os
     ) os
where prev_status is null or prev_status <> status;

【讨论】:

  • 谢谢,这样做了,但我将无法找到状态的最后一个employee_id。
  • @AdamS 。 . .您的问题似乎甚至没有提到员工 ID。
猜你喜欢
  • 2021-10-21
  • 2013-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 2015-09-23
  • 2020-08-11
  • 1970-01-01
相关资源
最近更新 更多