作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
背景故事:我有一个数据库,其中包含卡车司机的数据点,也包含。在卡车上时,驾驶员可以具有“ driverstatus”状态。我想做的是按驾驶员,卡车将这些状态分组。
到目前为止,我已经尝试使用LAG / LEAD来提供帮助。这样做的原因是,我可以告诉驾驶员何时发生驱动程序状态更改,然后可以将该行标记为具有该状态的最后日期时间。
这本身是不够的,因为我需要按状态和日期对状态进行分组。为此,我拥有诸如DENSE_RANK之类的东西,但是我无法设法获得有关ORDER BY子句的正确信息。
这是我的测试数据,这是我许多人在排名中挣扎的一种尝试。
/****** Script for SelectTopNRows command from SSMS ******/
DECLARE @SomeTable TABLE
(
loginId VARCHAR(255),
tractorId VARCHAR(255),
messageTime DATETIME,
driverStatus VARCHAR(2)
);
INSERT INTO @SomeTable (loginId, tractorId, messageTime, driverStatus)
VALUES('driver35','23533','2018-08-10 8:33 AM','2'),
('driver35','23533','2018-08-10 8:37 AM','2'),
('driver35','23533','2018-08-10 8:56 AM','2'),
('driver35','23533','2018-08-10 8:57 AM','1'),
('driver35','23533','2018-08-10 8:57 AM','1'),
('driver35','23533','2018-08-10 8:57 AM','1'),
('driver35','23533','2018-08-10 9:07 AM','1'),
('driver35','23533','2018-08-10 9:04 AM','1'),
('driver35','23533','2018-08-12 8:07 AM','3'),
('driver35','23533','2018-08-12 8:37 AM','3'),
('driver35','23533','2018-08-12 9:07 AM','3'),
('driver35','23533','2018-06-12 8:07 AM','2'),
('driver35','23533','2018-06-12 8:37 AM','2'),
('driver35','23533','2018-06-12 9:07 AM','2')
;
SELECT *, DENSE_RANK() OVER(PARTITION BY
loginId, tractorId, driverStatus
ORDER BY messageTime ) FROM @SomeTable
;
loginId tractorId startTime endTime driverStatus
driver35 23533 2018-08-10 8:33 AM 2018-08-10 8:56 AM 2
driver35 23533 2018-08-10 8:57 AM 2018-08-10 9:07 AM 1
driver35 23533 2018-08-12 8:07 AM 2018-08-12 9:07 AM 3
最佳答案
WITH drivers_data AS
(
SELECT *,
row_num = ROW_NUMBER()
OVER (PARTITION BY loginId,
tractorId,
CAST(messageTime AS date),
driverStatus
ORDER BY messageTime),
row_num_all = ROW_NUMBER()
OVER (PARTITION BY loginId,
tractorId
ORDER BY messageTime),
first_date = FIRST_VALUE (messageTime)
OVER (PARTITION BY loginId,
tractorId,
CAST(messageTime AS date),
driverStatus
ORDER BY messageTime),
last_date = LAST_VALUE (messageTime)
OVER (PARTITION BY loginId,
tractorId,
CAST(messageTime AS date),
driverStatus
ORDER BY messageTime
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM @t
)
SELECT loginId, tractorId, first_date, last_date, driverStatus
FROM drivers_data
WHERE row_num = 1
ORDER BY row_num_all;
FIRST_VALUE
是我们方便的函数。它只是检索第一个日期时间出现。
LAST_VALUE
窗口函数是正确的。但是使用它很棘手,需要更多的解释。如您所见,我明确使用特殊的框架
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
。但为什么?让我解释。让我们使用默认框架获取日期
10/8/2018
和状态
2
的一部分输出。我们得到以下结果:
LAST_VALUE
使用默认框架
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
-这意味着最后一行始终是窗口中的当前行。这是幕后故事。创建三个窗口。每行都有自己的窗口。然后,它从窗口检索最后一行:
UNBOUNDED FOLLOWING
仅表示此-当前窗口的最后一行。
WHERE row_num = 1
。这很简单:由于所有行都具有关于首个日期和最后日期的相同信息,因此我们只需要第一行。
ORDER BY row_num_all
。这是您正确订购的地方。
8/10/18 8:57 AM
和状态
1
,最后日期必须为
10/8/2018 9:07 AM
-而不是您所提到的
10/8/2018 9:04 AM
。
12/6/2018
和状态
2
缺少输出。
FIRST_VALUE
和
LAST_VALUE
的工作方式的说明。
partition
列。
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
。这意味着该行在分区的起始位置和当前行之间获得窗口。如果您不提及框架,则默认框架会起作用。
row 1
至
row 2
列中,并用颜色标记。行号对应于
row_num_all
字段。
FIRST_VALUE
窗口函数。
LAST_VALUE
窗口函数。
last_date
字段向我们显示了不正确的结果-它反映了当前行的日期。
LAST_VALUE
将在其上运行的框架:
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
。如您所见,每行的窗口现在位于当前行和分区末尾之间。在这种情况下,
LAST_VALUE
将正确地从窗口的最后一行获取日期。现在,
last_date
字段中的结果正确。
关于tsql - 离岛与缺口问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51846536/
我是一名优秀的程序员,十分优秀!