Tsql SQL合并开始日期和结束日期

Tsql SQL合并开始日期和结束日期,tsql,date,merge,Tsql,Date,Merge,我想合并一个日志事件中的多个开始日期和结束日期,以便一个日期有一行 输入表为: 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/20

我想合并一个日志事件中的多个开始日期和结束日期,以便一个日期有一行

输入表为:

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
如果你能帮我找到解决办法,我将不胜感激! 我的最后一个想法是做一个疯狂的结合所有的夫妇和单身者行与最后一组由

谢谢你的帮助

问候,,
François

这与您的样本数据和预期结果相符,但我有一种烦人的感觉,我遗漏了一些边缘案例:

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')
基本上,我们将每一行与逻辑上位于其后的行连接起来。我们忽略上一行和下一行。然后我们只需要计算出它是向下,向上正常,向下,向下只报告第一行的值还是向上,向上只报告第二行的值

结果:

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

我已经将您的想法应用到我的现实世界中,它在存储过程中工作得非常完美。谢谢你! 但是我的SQL客户端不支持存储过程。。。我真丢脸

所以我决定用pamareters创建一个表函数来调用这个SQL代码

不幸的是,在我的使用中,我没有找到使用名为Event的中间编号表的方法。。。 我在网上犯了以下错误;活动包括: ==>函数中包含的select语句无法向客户端返回数据

下面是我完成的函数代码:

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<=@dateStart)
        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>=@dateStart)

RETURN 
结束

你能想出一个神奇的解决办法吗

再次感谢你的帮助!
弗朗索瓦

太棒了!谢谢你的回答!您是否有一个解决方案,只使用一个SELECT和行号?我不确定我的最终SQL客户端是否允许这样的请求。。。不管怎样,听起来不错