2014-10-08 220 views
1

我想從一個日誌事件合併幾個開始日期和結束日期(所以1行爲一個日期)。SQL合併開始日期和結束

輸入表:

Ord Desc2 Date_Time 
-------------------------- 
0  Down  1/1/2014  ==> Not merged because no Up after 
1  Down  1/2/2014  ==> Rows 1 and 2 should be merged 
2  Up  1/3/2014  
5  Down  1/4/2014  ==> Rows 5 and 12 should be merged 
12  Up  1/6/2014  
13  Up  1/7/2014  ==> Not merged because no Down before 

所以導致我在尋找將是:

Ord DesactivationDateTime ActivationDateTime 
---------------------------------------------------- 
0  1/1/2014 
1  1/2/2014     1/3/2014 
5  1/4/2014     1/6/2014 
13        1/7/2014 

SQL請求我發現這是一個,但它僅適用於向上/向下夫婦:

SELECT EventsDesactivation.Ord 
    , EventsDesactivation.Desc2 
    , EventsDesactivation.Date_Time AS DesactivationDateTime 
    , MIN(EventsActivation.Date_Time) AS ActivationDateTime 
FROM Journal AS EventsDesactivation 

LEFT OUTER JOIN Journal AS EventsActivation 

ON EventsActivation.Module=EventsDesactivation.Module --This is one of common rows not displayed in this sample... 

WHERE 
    (EventsDesactivation.Desc2 = 'Down') 
    AND (EventsActivation.Desc2 = 'Up') 
    AND (EventsActivation.Ord > EventsDesactivation.Ord) 
GROUP BY EventsDesactivation.Ord, EventsDesactivation.Desc2, EventsDesactivation.Date_Time 

如果你能幫我找到解決方案,我將不勝感激! 我最後的想法是做一個瘋狂的聯盟所有夫婦和單打最後一個GROUP BY行...

感謝您的幫助!

問候, 弗朗索瓦

回答

0

此相匹配的樣本數據和預期的結果,但是我有一種揮之不去的感覺,我錯過了一些邊緣的情況下(S):

declare @t table (Ord int, Desc2 varchar(13),Date_Time date) 
insert into @t(Ord,Desc2,Date_Time) values 
(0  ,'Down','20140101'), 
(1  ,'Down','20140102'), 
(2  ,'Up','20140103'),  
(5  ,'Down','20140104'), 
(12 ,'Up','20140106'), 
(13 ,'Up','20140107') 

;With numbered as (
    select Ord,Desc2,Date_Time, 
     ROW_NUMBER() OVER (ORDER BY Ord /* or date_time? */) as rn 
    from 
     @t 
) 
select 
    CASE WHEN n1.Desc2='Up' and n2.Desc2='Up' THEN n2.Ord ELSE n1.Ord END, 
    CASE WHEN n1.Desc2='Up' and n2.Desc2='Up' THEN NULL ELSE n1.Date_Time END, 
    CASE WHEN n1.Desc2='Down' and n2.Desc2='Down' THEN NULL ELSE n2.Date_Time END 
from 
    numbered n1 
full outer join 
    numbered n2 
     on 
      n1.rn = n2.rn - 1 
where 
    not (n1.Desc2='Up' and n2.Desc2='Down') 

基本上,我們加入每行都有邏輯上在它之後的行。我們忽略了Up行,後面跟着Down行。然後,我們只需要工作,如果它是Down,Up(正常),Down,Down(僅報告第一行的值)或Up,Up(只報告第二行的值)

結果:

----------- ---------- ---------- 
0   2014-01-01 NULL 
1   2014-01-02 2014-01-03 
5   2014-01-04 2014-01-06 
13   NULL  2014-01-07 
+0

太棒了!感謝這個答案!你有解決方案只有一個SELECT和ROW_NUMBER()使用?我不確定我的最終SQL客戶端是否會允許這樣的請求......無論如何,聽起來不錯! :) – Francois 2014-10-08 12:46:08

0

我已經將你的想法應用於我的真實世界,並且它在存儲過程中完美工作。感謝那! 但是我的SQL客戶端不支持存儲過程...對我感到羞恥!

所以我決定創建一個表函數(用pamareters)來調用這個SQL代碼。我有沒有找到方式來使用你的中間編號表(在我的使用中稱爲事件)... ... 我有以下錯誤行「; WITH事件AS」: ==>包括選擇語句如果函數不能將數據返回給客戶端。

下面是功能代碼我做:

CREATE FUNCTION fnSensorsDesactivations 
(
    @dateStartInString nvarchar(50) = '', 
    @dateEndInString nvarchar(50) = '', 
    @Unit nvarchar(50) = null, 
    @HoursToAddFromGMT int = -2, 
    @DesactivationEventsFilter nvarchar(50) = 'Validation et Désactivation%', 
    @BeforeDesactivationComment nvarchar(50) = 'Validation et Désactivation Capteur par ', 
    @AfterDesactivationComment nvarchar(50) = '. Commentaire : ', 
    @ActivationEventsFilter nvarchar(50) = 'Activation Capteur par%', 
    @BeforeActivationUsername nvarchar(50) = 'Activation Capteur par ' 
) 
RETURNS @TableTempToReturn TABLE 
(
    -- Add the column definitions for the TABLE variable here 
    --Ord int, 
    Unit nvarchar(50), 
    Module nvarchar(255), 
    Module_Description nvarchar(255), 
    DésactivationQui nvarchar(255), 
    DésactivationDateTime nvarchar(255), 
    DésactivationMessage nvarchar(255), 
    ActivationQui nvarchar(255), 
    ActivationDateTime nvarchar(255) 
) 
AS 
BEGIN 
    DECLARE @ExcludeOrds AS nvarchar(255) -- Must be comma separated and also at first and last character 
    DECLARE @dateStart AS datetime -- to cast datetime from string because Dream Report is not able to pass parameters with formulas 
    DECLARE @dateEnd AS datetime -- to cast datetime from string because Dream Report is not able to pass parameters with formulas 
    SET @ExcludeOrds=',,,,,,,,,' 
IF @dateStartInString='' OR @dateEndInString='' 
    BEGIN 
     --Init dates from yesterday to today if they are null 
     SET @dateEnd=GETDATE() 
     SET @dateStart=DATEADD(year, -1, @DateEnd) 
    END 
ELSE 
    BEGIN 
     --Convert datetime from string to datetime format + hours from GMT to follow local datetime settings 
     SET @dateEnd=DATEADD(hour, @HoursToAddFromGMT, CONVERT(datetime, @dateEndInString, 121)) 
     SET @dateStart=DATEADD(hour, @HoursToAddFromGMT, CONVERT(datetime, @dateStartInString, 121)) 
    END 
IF @Unit IS NULL SET @Unit='WIP-BC2' 

--Calculate positions/orders of differents Activation and desactivation events 
;WITH Events AS -- Here is my SQL error: select statements included whithin a function cannot return a data to a client. 

(
    SELECT Ord, Unit, Module, Module_Description, Desc2, Date_Time, 
     ROW_NUMBER() OVER (ORDER BY Unit, Module, Ord) AS rn 
    FROM 
     EJournal.dbo.Journal 
    WHERE 
     Date_Time <= @dateEnd 
     AND Unit = @Unit 
     AND (Desc2 like @DesactivationEventsFilter 
       OR Desc2 like @ActivationEventsFilter) 
     --AND (Date_Time like @ActivationEventsFilter and Date_Time<[email protected]) 
     AND CHARINDEX(CAST(Ord AS nvarchar), @ExcludeOrds,1)=0 
) 

--Depending on desactivation and activation orders, select good Events in Activation/descativation columns 
SELECT 
    --n1.Ord,n2.Ord, n1.Desc2, n2.Desc2, 
    n1.Module 
    , n1.Module_Description 
    , CASE 
     WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter 
      THEN '' 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(LEFT(SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255) 
        , CHARINDEX(@AfterDesactivationComment, SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255)) - 1), '') 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(LEFT(SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255), '') 
        , CHARINDEX(@AfterDesactivationComment, SUBSTRING(n1.Desc2, LEN(@BeforeDesactivationComment)+2, 255)) - 1) 
     ELSE '' 
     END AS DésactivationQui 
    , CASE 
     WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter 
      THEN '' 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(CONVERT(nvarchar, n1.Date_Time, 121), '') 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(CONVERT(nvarchar, n1.Date_Time, 121), '') 
     ELSE '' 
    END AS DésactivationDateTime 
    , CASE 
     WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter 
      THEN '' 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @ActivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(SUBSTRING(n1.Desc2, CHARINDEX(@AfterDesactivationComment, n1.Desc2)+LEN(@AfterDesactivationComment), 255) , '') 
     WHEN n1.Desc2 like @DesactivationEventsFilter AND (n2.Desc2 like @DesactivationEventsFilter OR n2.Ord IS NULL) 
      THEN ISNULL(SUBSTRING(n1.Desc2, CHARINDEX(@AfterDesactivationComment, n1.Desc2)+LEN(@AfterDesactivationComment), 255) , '') 
     ELSE '' 
    END AS DésactivationMessage 
    , CASE 
     WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter 
      THEN ISNULL(SUBSTRING(n2.Desc2, LEN(@BeforeActivationUsername)+2, 255),'') 
     WHEN (n1.Desc2 like @DesactivationEventsFilter OR n1.Ord IS NULL) AND n2.Desc2 like @ActivationEventsFilter 
      THEN ISNULL(SUBSTRING(n2.Desc2, LEN(@BeforeActivationUsername)+2, 255), '') 
     --WHEN n1.Desc2 like @DesactivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter THEN '' 
     -- THEN '' 
     ELSE '' 
    END AS ActivationQui 
    , CASE 
     WHEN n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @ActivationEventsFilter 
      THEN ISNULL(CONVERT(nvarchar, n2.Date_Time, 121),'') 
     WHEN (n1.Desc2 like @DesactivationEventsFilter OR n1.Ord IS NULL) AND n2.Desc2 like @ActivationEventsFilter 
      THEN ISNULL(CONVERT(nvarchar, n2.Date_Time, 121),'') 
     --WHEN n1.Desc2 like @DesactivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter 
     -- THEN '' 
     ELSE '' 
    END AS ActivationDateTime 

FROM 
    Events n1 
FULL OUTER JOIN 
    Events n2 
    ON  n1.rn = n2.rn - 1 
      AND n1.Unit=n2.Unit 
      AND n1.Module=n2.Module 

WHERE NOT (n1.Desc2 like @ActivationEventsFilter AND n2.Desc2 like @DesactivationEventsFilter) 
     AND n1.Desc2 like @DesactivationEventsFilter 
     AND n1.Date_Time <= @dateEnd 
     --AND n2.Date_Time <= @dateEnd 
     AND (n2.Ord IS NULL OR n2.Date_Time>[email protected]) 

RETURN 

END

你會一直爲它神奇的解決方案?

再次感謝您的幫助! François

相關問題