Получить следующий ряд не работает из выбранного на основе даты и времени - PullRequest
0 голосов
/ 03 марта 2019

У меня есть следующие данные, и я хочу иметь возможность поместить все строки в одну строку на основе идентификатора типа остановки.Таким образом, тип стопа в порядке, что означает, что 0 или 2 будут предшествовать 3. Я считаю, что Lead - это то, что я хочу использовать, но, похоже, не работает так, как я хочу, и не смог понять, почему.

Вот так выглядят необработанные данные, основанные на времени по Гринвичу.

OrderId          GmtDeliveryDateTime        StopTypeId
3650             2019-01-11 13:04:44.000        0       
3650             2019-01-11 14:22:09.000        3       
3650             2019-01-11 15:13:35.000        2       
3650             2019-01-11 16:05:14.000        3

И я хочу, чтобы они выглядели так:

OrderId  GmtDeliveryDateTime    StopTypeId   GmtDeliveryDateTime    StopTypeId
3650    2019-01-11 13:04:44.000     0       2019-01-11 14:22:09.000     3
3650    2019-01-11 15:13:35.000     2       2019-01-11 16:05:14.000     3

Вот запрос, который я использую:

SELECT *
FROM (
    SELECT OrderId,
           GmtDeliveryDateTime,
           StopTypeId,        
           LEAD(StopTypeId) OVER (ORDER BY GmtDeliveryDateTime, StopTypeId) NxtStop
    FROM table
)

Вот результат, полученный выше:

OrderId GmtDeliveryDateTime     StopTypeId  NxtStop
3650    2019-01-11 13:04:44.000     0         2
3650    2019-01-11 15:13:35.000     2         2
3650    2019-01-11 14:22:09.000     3         3
3650    2019-01-11 16:05:14.000     3         2

Что не так с моим запросом?

Ответы [ 5 ]

0 голосов
/ 03 марта 2019

Если вы можете гарантировать, что строки чередуются, вы можете сделать:

SELECT t.*
FROM (SELECT OrderId,
             GmtDeliveryDateTime,
             StopTypeId,        
             LEAD(GmtDeliveryDateTime) OVER (PARTITION BY OrderId ORDER BY GmtDeliveryDateTime, StopTypeId) as next_GmtDeliveryDateTime,
             LEAD(StopTypeId) OVER (PARTITION BY OrderId ORDER BY GmtDeliveryDateTime, StopTypeId) as next_StopTypeId
      FROM table t
     ) t
WHERE StopTypeId <> 3;
0 голосов
/ 03 марта 2019

Я знаю, что другие ответили, но я использовал ваш первоначальный запрос и слегка изменил его, чтобы получить желаемые результаты:

DROP TABLE IF EXISTS #SO;

CREATE TABLE #SO
    (
        OrderID INT ,
        DeliveryDate DATETIME ,
        StopTypeID INT
    );

INSERT INTO #SO ( OrderID ,
                  DeliveryDate ,
                  StopTypeID )
VALUES ( 3650, '2019-01-11 13:04:44.000', 0 ) ,
       ( 3650, '2019-01-11 14:22:09.000', 3 ) ,
       ( 3650, '2019-01-11 15:13:35.000', 2 ) ,
       ( 3650, '2019-01-11 16:05:14.000', 3 );

SELECT x.OrderID ,
       x.DeliveryDate ,
       x.StopTypeID ,
       x.NxtStop ,
       ROW_NUMBER () OVER ( ORDER BY x.DeliveryDate ) AS rownumber
INTO   #TestData
FROM
       (
           SELECT OrderID ,
                  DeliveryDate ,
                  StopTypeID ,
                  LEAD ( StopTypeID ) OVER ( ORDER BY DeliveryDate , StopTypeID ) NxtStop
           FROM   #SO
       ) AS x;

SELECT a.OrderID ,
      a.DeliveryDate ,
      a.StopTypeID ,
      b.DeliveryDate ,
      b.StopTypeID
FROM  #TestData AS a
      INNER JOIN #TestData AS b ON b.OrderID = a.OrderID
                                   AND a.NxtStop = b.StopTypeID
                                   AND a.rownumber + 1 = b.rownumber
WHERE a.StopTypeID < b.StopTypeID;

DROP TABLE IF EXISTS #TestData;
0 голосов
/ 03 марта 2019

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

Вот решение, которое использует LAG() в подзапросе для восстановления соответствующих значений и ROW_NUMBER() для присвоения номера каждой записи, упорядоченного по GmtDeliveryDateTime.Внешний запрос отфильтровывает одну запись из двух, используя номер строки (четные номера строк отфильтровываются):

SELECT *
FROM (
    SELECT 
        OrderId,
        GmtDeliveryDateTime,
        StopTypeId,        
        LEAD(GmtDeliveryDateTime) OVER (ORDER BY GmtDeliveryDateTime) NxtGmtDeliveryDateTime,
        LEAD(StopTypeId) OVER (ORDER BY GmtDeliveryDateTime) NxtStopTypeId,
        ROW_NUMBER() OVER (ORDER BY GmtDeliveryDateTime) rn
    FROM mytable 
) x WHERE rn % 2 <> 0

Примечание: я удалил ORDER BY в StopTypeId, так как ваши образцы данныхне показывает дубликат GmtDeliveryDateTime.

Эта демонстрация на DB Fiddle с вашими примерами возвращает:

<code><pre>
OrderId | GmtDeliveryDateTime | StopTypeId | NxtGmtDeliveryDateTime | NxtStopTypeId | rn
------: | :------------------ | ---------: | :--------------------- | ------------: | :-
   3650 | 11/01/2019 00:00:00 |          0 | 11/01/2019 00:00:00    |             3 | 1
   3650 | 11/01/2019 00:00:00 |          2 | 11/01/2019 00:00:00    |             3 | 3
0 голосов
/ 03 марта 2019

Вы можете попробовать ниже -

ДЕМО

SELECT OrderId,
       MIN(GmtDeliveryDateTime) as starttime,
       MIN(StopTypeId) as startStopTypeId,
       MAX(GmtDeliveryDateTime) as endtime,
       MAX(StopTypeId) as nextStopTypeId
       from
(
SELECT t.*,
row_number() over(order by GmtDeliveryDateTime)-
sum(case when StopTypeId=3 then 1 else 0 end) over(partition by OrderId order by GmtDeliveryDateTime) as grp
      FROM  t1 t
)A group by grp,OrderId

ВЫХОД:

OrderId starttime           startStopTypeId endtime             nextStopTypeId
3650    11/01/2019 13:04:44   0             11/01/2019 14:22:09  3
3650    11/01/2019 15:13:35   2             11/01/2019 16:05:14  3
0 голосов
/ 03 марта 2019

Предполагая, что строки с 0,3 или 2,3 в качестве последовательных идентификаторов остановки идентифицируют группу для данного идентификатора заказа , вы можете сделать это, используя промежуточную сумму для классификации последовательных 0,3 или 2,3строк в группу, а затем используйте group by, чтобы получить желаемый результат.

SELECT OrderId,
       MIN(GmtDeliveryDateTime),
       MIN(StopTypeId),
       MAX(GmtDeliveryDateTime),
       MAX(StopTypeId)
FROM (SELECT t.*,sum(case when StopTypeId=3 then 1 else 0 end) over(partition by OrderId order by GmtDeliveryDateTime) as grp
      FROM table t
     ) t 
GROUP BY OrderId,grp
...