2016-10-17 70 views
2

我有如下數據(視圖):添加附加行

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:05.000','9/9/16 10:48:08.000','Big'), 
    ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44:10.000','9/9/16 10:49:40.000','Big'), 
    ('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50:03.000','9/9/16 10:51:04.000','Small'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51:07.000','4/4/16 13:58:09.000','Big'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04:04.000','4/4/16 14:29:00.000','Small'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51:02.000','4/4/16 14:58:00.000','Big'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04:06.000','4/4/16 15:29:08.000','Small'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45:08.000','4-4-16 15:55:09.000','Big'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 16:22:08.000','4-4-16 16:40:09.000','Big'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 16:50:04.000','4/4/16 16:55:00.000','Small'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 17:05:02.000','4/4/16 17:20:00.000','Big'), 
    ('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 17:22:06.000','4/4/16 17:29:08.000','Small'), 
    ('11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04:01.000','4/4/16 16:45:00.000','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 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 Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 15:04:06.000 2016-04-04 15:29:08.000 Small Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 15:45:08.000 2016-04-04 15:55:09.000 Big Big 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 16:22:08.000 2016-04-04 16:40:09.000 Big Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 16:50:04.000 2016-04-04 16:55:00.000 Small Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 17:05:02.000 2016-04-04 17:20:00.000 Big Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 17:22:06.000 2016-04-04 17:29:08.000 Small Small 
11PIC41010.PV 11-PSV-401002W 11-PSV-401002D  2016-04-04 16:04:01.000 2016-04-04 16:45:00.000 Big Big 

我需要申請多一個例外,每當序列標籤欄下方出現一組,應該經過小前大與開始時間,結束時間和Tag_new添加相應的aditional的行,開始時間應該是1秒比之前的日期晚,endtime和endtime比starttime晚1秒d Tag_new是 「壞」:

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:29:01.000 2016-04-04 14:29:02.000 Bad Bad 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 14:51:02.000 2016-04-04 14:58:00.000 Big Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 15:04:06.000 2016-04-04 15:29:08.000 Small Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 15:45:08.000 2016-04-04 15:55:09.000 Big Big 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 16:22:08.000 2016-04-04 16:40:09.000 Big Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 16:50:04.000 2016-04-04 16:55:00.000 Small Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 16:55:01.000 2016-04-04 16:55:02.000 Bad Bad 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 17:05:02.000 2016-04-04 17:20:00.000 Big Small 
11PIC41010.PV 11-PSV-401002A 11-PSV-401002B  2016-04-04 17:22:06.000 2016-04-04 17:29:08.000 Small Small 
11PIC41010.PV 11-PSV-401002W 11-PSV-401002D  2016-04-04 16:04:01.000 2016-04-04 16:45:00.000 Big Big 
+0

我投了這個票,因爲問題相當好。有示例代碼來複制'n'paste,自己的努力和一個非常明確的解釋。整個方法聞起來有點尷尬 - 複雜... SQL Server可能不是最好的工具。但是這個問題本身並不值得「因爲不清楚」而得到「不公平」,也不值得投票。只有我2美分... – Shnugo

+0

感謝Shnugo爲其投票 –

+0

爲什麼你要轉貼這個問題,這裏回答了這個問題:http://stackoverflow.com/questions/40026002/group-and-order-with-additional-exception/40027420#40027420? – iamdave

回答

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:05.000','9/9/16 10:48:08.000','Big'), 
('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:44:10.000','9/9/16 10:49:40.000','Big'), 
('10PIC700422.PV 10-PSV-700073A 10-PSV-700073B','9/9/16 10:50:03.000','9/9/16 10:51:04.000','Small'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 12:51:07.000','4/4/16 13:58:09.000','Big'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:04:04.000','4/4/16 14:29:00.000','Small'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 14:51:02.000','4/4/16 14:58:00.000','Big'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 15:04:06.000','4/4/16 15:29:08.000','Small'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 15:45:08.000','4-4-16 15:55:09.000','Big'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4-4-16 16:22:08.000','4-4-16 16:40:09.000','Big'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 16:50:04.000','4/4/16 16:55:00.000','Small'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 17:05:02.000','4/4/16 17:20:00.000','Big'), 
('11PIC41010.PV 11-PSV-401002A 11-PSV-401002B','4/4/16 17:22:06.000','4/4/16 17:29:08.000','Small'), 
('11PIC41010.PV 11-PSV-401002W 11-PSV-401002D','4/4/16 16:04:01.000','4/4/16 16:45:00.000','Big'); 

- 增加一個正在運行的行數來查詢併爲所有original

WITH YourQueryEnhanced AS 
(
    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 
    ,ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS SortInx --You should put a secure ORDER BY here!!! 
    ,0 AS InnerSortInx 
    From @YourTable 
) 

--USE LAG()檢測到您的序列0。重疊的壞序列有一個問題!

,BadMarked AS 
(
    SELECT * 
     ,CASE WHEN LAG([Tag],1) OVER(Order By SortInx)='Small' 
       AND LAG([Tag],2) OVER(Order By SortInx)='Big' 
       AND LAG([Tag],3) OVER(Order By SortInx)='Small' THEN 1 ELSE 0 END AS BadSequence 

    FROM YourQueryEnhanced 
) 

- 這將選擇所有original行,將增加一個bad一行標記爲BadSequence每一行。該SortInx設置爲上一個值,內sortInx設置爲1,因此ORDER BY將推動在適當的位置bad

SELECT * 
    FROM BadMarked 

    UNION ALL 

    SELECT [Event],[Start],[End],'Bad','Bad',SortInx-1,1,2 
    FROM BadMarked 
    WHERE BadMarked.BadSequence=1 
    ORDER BY SortInx,InnerSortInx 

注意

這將增加一個更壞的一行到你的結果,正如你在預期的結果中所說的那樣。

原因是你的線條3到7,你有小,大,小,大,小。中間small屬於兩個序列。

必須要麼在地方有更多的邏輯解決這個(多次調用LAG()看進一步回),其中檢測到不良序列,或者你包的最後選擇爲一個更CTE和再次使用LAG()去除壞你不想要的行。

+0

Shnugo,感謝代碼,但這似乎不是我需要的。 –

+0

@JoeGreen,請詳細說明......爲什麼不呢? – Shnugo

+0

好吧,我會嘗試處理額外的行(仍然不知道該怎麼做),那麼在starttime和endtime中添加1秒是什麼? –

1

@Shnugo:你真的很親密。感謝解決方案!

WITH YourQueryEnhanced AS 
(
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 
,ROW_NUMBER() OVER(Partition By [Event] Order By Start) AS SortInx --You  should put a secure ORDER BY here!!! 
,0 AS InnerSortInx 
From @YourTable 
), BadMarked AS 
(
SELECT * 
    ,CASE WHEN LAG([Tag],1) OVER(Order By SortInx)='Small' 
      AND LAG([Tag],2) OVER(Order By SortInx)='Big' 
      AND LAG([Tag],3) OVER(Order By SortInx)='Big' THEN 1 ELSE 0 END  AS BadSequence 
FROM YourQueryEnhanced 
) 
select * from 
(
SELECT * 
FROM BadMarked 
UNION ALL 
    SELECT [Event],DATEADD(s, -1, [Start]) [Start], [End],'Bad','Bad',SortInx-1,1,2 
FROM BadMarked 
WHERE BadMarked.BadSequence=1 
) a order by [Event] 
,[Start] 
+0

Hi Shnugo,我找不到按鈕「接受」。 –

+0

接受了它。再次感謝Shnugo! –