我有以下数据,我希望能够根据停止类型id将所有行放到一行中。因此,止损类型是按顺序排列的,这意味着0或2将在3之前。我相信Lead是我要使用的东西,但似乎无法像我想要的那样工作并且无法弄清楚为什么
这是基于GMT日期时间的原始数据。
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
我的查询出了什么问题?
答案 0 :(得分:1)
如果可以保证行是交错的,则可以执行以下操作:
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;
答案 1 :(得分:0)
假设以0,3
或2,3
作为连续止损ID的行为给定订单ID标识了一个组,您可以使用运行总和对连续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
答案 2 :(得分:0)
我了解到您正在尝试将记录分为两部分,每条记录与下一个记录按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
。
此 demo on DB Fiddle 及其示例数据将返回:
<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
</pre>
答案 3 :(得分:0)
您可以在下面尝试-
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
答案 4 :(得分:0)
我知道其他人已经回答了,但是我使用了您的初始查询并将其稍加修改以得到所需的结果:
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;