дата для строки, которая соответствует моему условию, только один раз в строке - PullRequest
0 голосов
/ 27 февраля 2019

Я хочу сделать дату между двумя датами в разных строках, только если строки имеют условие.

Моя таблица выглядит следующим образом, с дополнительными столбцами (например, 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 строки в моем выборе, которые представляют разницу между датами с идентификатора 5-3 и идентификатора 2-1.

На данный момент я пришел с запросом, который даетмне разница между датами с идентификаторами 5-3, 5-1 и 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, поскольку другие строки могутбыть между теми, на которых я хочу сделать разность.

Как я могу сделать датировку только на первых строках, которые соответствуют моим условиям?

РЕДАКТИРОВАТЬ : сделатьэто более ясно

Мое состояние - это имя события, и я хочу рассчитать время между появлением моего события 1 и моего события 2 и заполнить столбец с именем time, например.

@ Salman Ответ действительно близок к тому, что я хочу, но не будетработать, когда мое событие 2 не происходит (чего не было в моем первоначальном примере)

, то есть в таблице, подобной следующей, будет установлено значение между идентификатором строки 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 голосов
/ 27 февраля 2019

Я бы перечислил значения и затем использовал бы оконные функции для разницы.

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;

Я не могу сказать, как вы хотите, чтобы результаты выглядели.Эта версия выводит только различия с идентификаторами строк, которые вас интересуют.Разница также может применяться к исходным строкам, а не помещаться в итоговые строки.

0 голосов
/ 27 февраля 2019

Возможно, вы хотите сопоставить идентификаторы с ближайшим меньшим идентификатором.Для этого вы можете использовать оконные функции:

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 state с with this.Если у вас есть несовпадающие пары, он вернет NULL.

0 голосов
/ 27 февраля 2019

В идеале вы хотите LEADIF/LAGIF функции, потому что вы ищете предыдущую строку, где условие = 'с этим'.Поскольку нет LEADIF/LAGIF, я думаю, что лучший вариант - использовать OUTER/CROSS APPLY с TOP 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
0 голосов
/ 27 февраля 2019

попробуйте с помощью аналитической функции 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')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...