【问题标题】:Group and order with additional exception分组和订购有额外的例外
【发布时间】:2016-10-18 00:03:19
【问题描述】:

我有下表:

 Declare @YourTable table ([Event] varchar(100),[Start] DateTime,[End] DateTime, [Tag] varchar(25))
 Insert Into @YourTable values
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44','9/9/16 10:49','Big'),
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50','9/9/16 10:51','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51','4/4/16 13:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04','4/4/16 14:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51','4/4/16 14:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04','4/4/16 15:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45','4-4-16 15:55','Big'),
 ('11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04','4/4/16 16:45','Big')

并使用以下查询来获取我需要的结果,按事件分组并按开始顺序,并在小到大时从大到小:

 Select [Event]
  ,[Start]
  ,[End] 
  ,[Tag]
  ,[Tag_new] = case when Tag='Big' and 'Small' = Lead(Tag,1,Tag) over (Partition By Event Order By Start) then 'Small' else tag end
  From  @YourTable

   Event                                          Start         End             Tag    Tag_new
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:44  9-9-16 10:49    Big    Small
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:50  9-9-16 10:51    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 12:51  4-4-16 13:58    Big    Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:04  4-4-16 14:29    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:51  4-4-16 14:58    Big    Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:04  4-4-16 15:29    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:45  4-4-16 15:55    Big    Big
   11PIC41010.PV 11-PSV-401002W 11-PSV-401002D    4-4-16 16:04  4-4-16 16:45    Big    Big

但是每当下面的序列出现在组中的 Tag 列中时,我需要再应用一个例外,Tag_new 列应该是“Small2”,从 Big 到 Tag 列中的下一个 Big:

  Small
  Big
  Small

我想得到以下结果:

   Event                                          Start         End             Tag    Tag_new
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:44  9-9-16 10:49    Big    Small
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:50  9-9-16 10:51    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 12:51  4-4-16 13:58    Big    Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:04  4-4-16 14:29    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:51  4-4-16 14:58    Big    Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:04  4-4-16 15:29    Small  Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:45  4-4-16 15:55    Big    Big
   11PIC41010.PV 11-PSV-401002W 11-PSV-401002D    4-4-16 16:04  4-4-16 16:45    Big    Big

对 iamdave 的更新:

当我在 big 之后还有一些小的时候,它会在 Big 之后变成第二个 Small,而 Small2 应该是 Small2,所以它应该是 Small2,直到下一个 Big:

 Declare @YourTable table ([Event] varchar(100),[Start] DateTime,[End] DateTime, [Tag] varchar(25))
 Insert Into @YourTable values
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44','9/9/16 10:49','Big'),
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50','9/9/16 10:51','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51','4/4/16 13:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04','4/4/16 14:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51','4/4/16 14:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04','4/4/16 15:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:30','4/4/16 15:32','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45','4-4-16 15:55','Big'),
 ('11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04','4/4/16 16:45','Big')

这里是输出,以防 Big 之后再小一些:

   Event                                          Start         End             Tag    Tag_new
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:44  9-9-16 10:49    Big    Small
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:50  9-9-16 10:51    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 12:51  4-4-16 13:58    Big    Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:04  4-4-16 14:29    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:51  4-4-16 14:58    Big    Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:04  4-4-16 15:29    Small  Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:30  4-4-16 15:32    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:45  4-4-16 15:55    Big    Big
   11PIC41010.PV 11-PSV-401002W 11-PSV-401002D    4-4-16 16:04  4-4-16 16:45    Big    Big

它应该如下所示:

   Event                                          Start         End             Tag    Tag_new
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:44  9-9-16 10:49    Big    Small
   10PIC700422.PV 10-PSV-700073A 10-PSV-700073B   9-9-16 10:50  9-9-16 10:51    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 12:51  4-4-16 13:58    Big    Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:04  4-4-16 14:29    Small  Small
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 14:51  4-4-16 14:58    Big    Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:04  4-4-16 15:29    Small  Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:30  4-4-16 15:32    Small  Small2
   11PIC41010.PV 11-PSV-401002A 11-PSV-401002B    4-4-16 15:45  4-4-16 15:55    Big    Big
   11PIC41010.PV 11-PSV-401002W 11-PSV-401002D    4-4-16 16:04  4-4-16 16:45    Big    Big

更新@iamdave: 再次为这种混乱感到抱歉,似乎更改为 small2 是错误的方向,因为如果我下面的序列很少,它会在我寻找将它们分开的时候给所有 small2:

Small 
Big 
Small
Small
Big
Small

这是我得到的:

                                       Event    Start                   End                     Tag  Tag_new
10PIC700422.PV 10-PSV-700073A 10-PSV-700073B    2016-09-09 10:44:05.000 2016-09-09 10:48:08.000 Big   Big
10PIC700422.PV 10-PSV-700073A 10-PSV-700073B    2016-09-09 10:44:10.000 2016-09-09 10:49:40.000 Big   Small
10PIC700422.PV 10-PSV-700073A 10-PSV-700073B    2016-09-09 10:50:03.000 2016-09-09 10:51:04.000 Small Small
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 12:51:07.000 2016-04-04 13:58:09.000 Big   Small
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 14:04:04.000 2016-04-04 14:29:00.000 Small Small
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 14:51:02.000 2016-04-04 14:58:00.000 Big   Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 15:04:06.000 2016-04-04 15:29:08.000 Small Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 15:45:08.000 2016-04-04 15:55:09.000 Big   Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 16:22:08.000 2016-04-04 16:40:09.000 Small Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 16:50:04.000 2016-04-04 16:55:00.000 Small Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 17:05:02.000 2016-04-04 17:20:00.000 Big   Small2
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B     2016-04-04 17:22:06.000 2016-04-04 17:29:08.000 Small Small2
11PIC41010.PV 11-PSV-401002W 11-PSV-401002D     2016-04-04 16:04:01.000 2016-04-04 16:45:00.000 Big   Big

因此,最好的解决方案是添加我在最近的问题中描述的额外行:

提前感谢您的帮助, S

【问题讨论】:

  • 这里的业务规则能不能解释的更清楚一点。这对我来说根本没有任何意义。你需要定义“下一个”。接下来作为一个概念需要一个命令。该数据的排序标准是什么?活动,开始吧?
  • 肖恩,标准是 - 按事件分组并按开始顺序
  • 第一个业务规则(已经在上面的查询中定义)是:按事件分组,按开始顺序,只要小后大,就从大到小。第二个:在序列时定义另一个组 - Small Big Small 出现在Tag中,Big是组的起点,直到下一个Big开始。希望对您有所帮助。

标签: sql-server tsql sql-server-2012


【解决方案1】:

这很丑陋,但我认为它可以满足您的需求?

Declare @YourTable table ([Event] varchar(100),[Start] DateTime,[End] DateTime, [Tag] varchar(25))
 Insert Into @YourTable values
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44','9/9/16 10:48','Big'),
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44','9/9/16 10:49','Big'),
 ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50','9/9/16 10:51','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51','4/4/16 13:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04','4/4/16 14:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51','4/4/16 14:58','Big'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04','4/4/16 15:29','Small'),
 ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45','4-4-16 15:55','Big'),
 ('11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04','4/4/16 16:45','Big');


 Select [Event]
  ,[Start]
  ,[End] 
  ,[Tag]
  ,[Tag_new] = case when Tag = 'Big'
                                    and Lead(Tag,1,'') over (Partition By Event
                                                            Order By Start
                                                            )
                                    = 'Small'
                                then 'Small'
                                else tag
                                end

  ,[Tag_new2] = case when (Tag = 'Big'
                            and lag(Tag,1,'') over  (Partition By Event
                                                        Order By Start
                                                        )
                                = 'Small'
                            and Lead(Tag,1,'') over (Partition By Event
                                                        Order By Start
                                                        )
                                = 'Small'
                        )

                        or (Tag = 'Small'
                            and lag(Tag,2,'') over  (Partition By Event
                                                    Order By Start
                                                    )
                                = 'Small'
                            and lag(Tag,1,'') over  (Partition By Event
                                                    Order By Start
                                                    )
                                = 'Big'
                            )
                    then 'Small2'
                    else case when Tag = 'Big'
                                    and Lead(Tag,1,'') over (Partition By Event
                                                            Order By Start
                                                            )
                                    = 'Small'
                                then 'Small'
                                else tag
                                end
                    end

  From  @YourTable;

响应您的更新,并假设您可以向暂存表添加一些列:

Declare @YourTable table (EventRN int, StartRN int, MaxStartRN int, [Event] varchar(100),[Start] DateTime,[End] DateTime, [Tag] varchar(25), [TagNext] varchar(25))
 Insert Into @YourTable values
 (null,null,null,'10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44','9/9/16 10:49','Big',null),
 (null,null,null,'10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50','9/9/16 10:51','Small',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51','4/4/16 13:58','Big',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04','4/4/16 14:29','Small',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51','4/4/16 14:58','Big',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04','4/4/16 15:29','Small',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:30','4/4/16 15:32','Small',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45','4-4-16 15:55','Big',null),
 (null,null,null,'11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04','4/4/16 16:45','Big',null);


update t
set EventRN = tt.EventRN
    ,StartRN = tt.StartRN
    ,MaxStartRN = tt.MaxStartRN
    ,TagNext = tt.TagNext
from @YourTable t
    inner join (
              select dense_rank() over (order by Event
                                        ) as EventRN
                    ,row_number() over (partition by Event
                                        order by Start
                                        ) as StartRN
                    ,count(1) over (partition by Event) as MaxStartRN
                    ,[Event]
                    ,[Start]
                    ,[End]
                    ,[Tag]
                    ,lead(Tag,1,null) over (partition by Event
                                                        order by Start
                                                        )
                        as TagNext
              from @YourTable
              ) tt
        on(t.[Event] = tt.[Event]
            and t.[Start] = tt.[Start]
            and t.[End] = tt.[End]
            and t.Tag = tt.Tag
            );

with cte as
(
    select EventRN
        ,StartRN
        ,MaxStartRN
        ,[Event]
        ,[Start]
        ,[End]
        ,Tag
        ,TagNext
        ,cast(null as varchar(25)) as TagPrev

        ,case when TagNext = 'Small'
                        then TagNext
                        else Tag
                        end as TagNew
    from @YourTable
    where EventRN = 1
        and StartRN = 1

    union all

    select t.EventRN
        ,t.StartRN
        ,t.MaxStartRN
        ,t.[Event]
        ,t.[Start]
        ,t.[End]
        ,t.Tag
        ,t.TagNext
        ,case when t.EventRN = c.EventRN then c.Tag else null end as TagPrev

        ,case when t.EventRN = c.EventRN and c.Tag = 'Small' and t.Tag = 'Big' and t.TagNext = 'Small'
                or t.EventRN = c.EventRN and c.TagNew = 'Small2' and t.Tag = 'Small'
            then 'Small2'
            else case when t.TagNext = 'Small'
                        then t.TagNext
                        else t.Tag
                        end
            end
    from cte c
        inner join @YourTable t
            on((c.StartRN < c.MaxStartRN
                and t.EventRN = c.EventRN
                and t.StartRN = c.StartRN+1
                )
                or (c.StartRN = c.MaxStartRN
                    and t.EventRN = c.EventRN+1
                    and t.StartRN = 1
                    )
                )
)
select [Event]
        ,[Start]
        ,[End]
        ,Tag
        ,TagNew
from cte
order by Event
        ,Start;

【讨论】:

  • iamdave,非常感谢代码,我目前没有要测试的 sql server,但只要它给出相同的结果就可以了。你们在帮助人们完成此类任务方面做得很好。
  • iamdave,我检查了一下,如果大后只有一个小的,它可以正常工作,但假设我还有几个小的,那么它将是小而不是小的 2,请参阅上面的更新。
  • @JoeGreen 用新方法更新了我的答案。
  • 致 iamdave:感谢代码更新!抱歉,我之前没有提到,这是一个视图而不是表格,但我会尝试采用您对视图选择的更新,
  • @JoeGreen 这仅在您可以更新所持有的值时才有效。如果你的源是一个视图,insert 视图的结果进入一个临时表,然后 update 临时表按照我上面的代码。
猜你喜欢
  • 2015-12-05
  • 2019-01-01
  • 2018-11-03
  • 1970-01-01
  • 2021-07-24
  • 2017-02-22
  • 2021-10-06
  • 2012-06-15
  • 1970-01-01
相关资源
最近更新 更多