满足我条件的行的datediff每行仅一次

时间:2019-02-27 11:18:08

标签: sql sql-server tsql datetime

仅当行中有条件时,我才想在不同行的2个日期之间进行datediff。

我的表如下所示,并带有其他列(如guid)

Id  | CreateDateAndTime        | condition
---------------------------------------------------------------
1   | 2018-12-11 12:07:55.273  |    with this 
2   | 2018-12-11 12:07:53.550  |    I need to compare this state 
3   | 2018-12-11 12:07:53.550  |    with this 
4   | 2018-12-11 12:06:40.780  |    state 3
5   | 2018-12-11 12:06:39.317  |    I need to compare this state 

在此示例中,我希望选择2行来表示ID 5-3和ID 2-1之间的日期差。

截至目前,我提出了一个请求,该请求为我提供了ID 5-3,ID 5-1和ID 2-1之间的日期差:

with t as (
      SELECT TOP (100000) 
          *
      FROM mydatatable

      order by CreateDateAndTime desc) 

      select 
      DATEDIFF(SECOND, f.CreateDateAndTime, s.CreateDateAndTime)  time

      from t f
      join t s on (f.[guid] = s.[guid] )
      where f.condition like '%I need to compare this state%'
      and s.condition like '%with this%'
        and (f.id - s.id) < 0 

我的问题是我无法将f.id-s.id设置为一个值,因为其他行可以位于我要进行比较的行之间。

如何仅在满足我条件的第一行上设置datediff?

编辑:使其更加清晰

我的条件是事件名称,我想计算事件1和事件2发生之间的时间,并填写一个名为time的列。

@Salman A answer确实很接近我想要的东西,除了在事件2未发生时(在我的初始示例中不是)

,它将无法工作

即在如下所示的表格中,它将使datediff在第5行和第2行之间

Id  | CreateDateAndTime        | condition
---------------------------------------------------------------
1   | 2018-12-11 12:07:55.273  |    with this 
2   | 2018-12-11 12:07:53.550  |    I need to compare this state 
3   | 2018-12-11 12:07:53.550  |    state 3
4   | 2018-12-11 12:06:40.780  |    state 3
5   | 2018-12-11 12:06:39.317  |    I need to compare this state 

我修改的代码:

WITH cte AS (
    SELECT id
         , CreateDateAndTime AS currdate
         , LAG(CreateDateAndTime) OVER (PARTITION BY guid ORDER BY id desc ) AS prevdate
         , condition
    FROM t
    WHERE condition IN ('I need to compare this state', 'with this ')
)
SELECT *
     ,DATEDIFF(second, currdate, prevdate) time
FROM cte
WHERE condition = 'I need to compare this state '
and DATEDIFF(second, currdate, prevdate) != 0
order by id desc

4 个答案:

答案 0 :(得分:1)

尝试使用解析函数lead()

    with cte as
(
select 1 as id, '2018-12-11 12:07:55.273' as CreateDateAndTime,'with this' as condition union all
select 2,'2018-12-11 12:07:53.550','I need to compare this state' union all
select 3,'2018-12-11 12:07:53.550','with this' union all
select 4,'2018-12-11 12:06:40.780','state 3' union all
select 5,'2018-12-11 12:06:39.317','I need to compare this state'


) select *, 
    DATEDIFF(SECOND,CreateDateAndTime,lead(CreateDateAndTime) over(order by Id))
    from cte    
     where condition in ('with this','I need to compare this state')

答案 1 :(得分:1)

也许您想将ID与最近的较小ID匹配。您可以为此使用窗口功能:

WITH cte AS (
    SELECT id
         , CreateDateAndTime AS currdate
         , CASE WHEN LAG(condition) OVER (PARTITION BY guid ORDER BY id) = 'with this'
                THEN LAG(CreateDateAndTime) OVER (PARTITION BY guid ORDER BY id) AS prevdate
         , condition
    FROM t
    WHERE condition IN ('I need to compare this state', 'with this')
)
SELECT *
     , DATEDIFF(second, currdate, prevdate)
FROM cte
WHERE condition = 'I need to compare this state'

CASE表达式将this statewith this匹配。如果您有不匹配的对,则它将返回NULL。

答案 2 :(得分:1)

理想情况下,您需要LEADIF/LAGIF函数,因为您正在寻找条件='with this'的上一行。由于没有LEADIF/LAGIF,我认为最好的选择是将OUTER/CROSS APPLYTOP 1一起使用,例如

CREATE TABLE #T (Id INT, CreateDateAndTime DATETIME, condition VARCHAR(28));    
INSERT INTO #T (Id, CreateDateAndTime, condition)
VALUES
    (1, '2018-12-11 12:07:55', 'with this'),
    (2, '2018-12-11 12:07:53', 'I need to compare this state'),
    (3, '2018-12-11 12:07:53', 'with this'),
    (4, '2018-12-11 12:06:40', 'state 3'),
    (5, '2018-12-11 12:06:39', 'I need to compare this state');


SELECT  ID1 = t1.ID,
        Date1 = t1.CreateDateAndTime,
        ID2 = t2.ID,
        Date2 = t2.CreateDateAndTime,
        Difference = DATEDIFF(SECOND, t1.CreateDateAndTime, t2.CreateDateAndTime)
FROM    #T AS t1
        CROSS APPLY
        (   SELECT  TOP 1 t2.CreateDateAndTime, t2.ID
            FROM    #T AS t2
            WHERE   t2.Condition = 'with this'
            AND     t2.CreateDateAndTime > t1.CreateDateAndTime
            --AND       t2.GUID = t.GUID
            ORDER BY CreateDateAndTime
        ) AS t2
WHERE   t1.Condition = 'I need to compare this state';

哪个给予:

ID1     Date1                       D2  Date2                       Difference
-------------------------------------------------------------------------------
2       2018-12-11 12:07:53.000     1   2018-12-11 12:07:55.000     2
5       2018-12-11 12:06:39.000     3   2018-12-11 12:07:53.000     74

答案 3 :(得分:1)

我将枚举值,然后使用窗口函数进行区别。

select min(id), max(id),
       datediff(second, min(CreateDateAndTime), max(CreateDateAndTime)) as seconds
from (select t.*,
             row_number() over (partition by condition order by CreateDateAndTime) as seqnum
      from t
      where condition in ('I need to compare this state', 'with this')
      ) t
group by seqnum;

我无法说出您想要结果如何。此版本仅输出差异以及您关心的行的ID。差异也可以应用于原始行,而不是放在摘要行中。