第一篇文章 - 为那个冗长的问题道歉。使用SQLServer2012
这将更好地说明我的需求:
我有代理商的活动日志 - 每次他们在我们的呼叫中心更改他们的电话状态。每个用户每天可以有几个或几百个。我需要输入一个日期时间,并让它返回每个人的PREVIOUS到该日期时间的状态。
目前,这是我的问题。这段代码告诉我我想要的东西,但减去我需要的一条信息:
SELECT
MAX(StatusDateTime),
UserId
FROM
AgentActivityLog
WHERE
StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12'
GROUP BY
UserId
order by 2,1
返回一个userid列表,我在2016年2月9日08:52:12之前收到了最新的条目。
2016-02-09 08:02:21.000 AbalosB
2016-02-09 08:06:12.000 AnkenbrD
2016-02-09 07:48:58.000 AzziV
2016-02-09 00:00:00.000 BachmayM
我的问题是我还需要包含另一个包含其所处状态名称的列。当我这样做时,它包含该范围内的每个唯一时间;我假设因为它现在为每个状态选择最大时间 - 而不是仅限最大时间。
将StatusKey添加到Select和Group By时返回的内容示例:
2016-02-09 08:01:43.000 AbalosB Gone Home
2016-02-09 08:02:21.000 AbalosB Available
2016-02-09 08:00:50.000 AnkenbrD Gone Home
2016-02-09 08:04:40.000 AnkenbrD On ACD Call
2016-02-09 08:06:02.000 AnkenbrD ACW - After Call Work
2016-02-09 08:06:12.000 AnkenbrD Available
我需要包含Status列,但我只需要在输入之前输入的条目。我这次使用了一个范围,我可以进入' 2/9/2016 08:52:12'和Id需要输入
答案 0 :(得分:0)
如果您只需要一条记录,即最新记录,则可以使用TOP
:
SELECT TOP 1 StatusDateTime, UserId, StatusKey
FROM AgentActivityLog
WHERE StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12'
ORDER BY StatusDateTime DESC
修改强>
要获取最新记录每个用户,请使用ROW_NUMBER
:
SELECT StatusDateTime, UserId, StatusKey
FROM (
SELECT StatusDateTime, UserId, StatusKey,
ROW_NUMBER() OVER (PARTITION BY UserId
ORDER BY StatusDateTime DESC) AS rn
FROM AgentActivityLog
WHERE StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12') t
WHERE t.rn = 1
答案 1 :(得分:0)
使用this jsfiddle和CTE
WITH Data AS (
SELECT
StartDateTime,
UserId,
StatusKey,
RANK() OVER(PARTITION BY UserId ORDER BY StartDateTime DESC) r
FROM AgentActivityLog
WHERE StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12'
)
SELECT * FROM Data WHERE r = 1
答案 2 :(得分:0)
您可以使用Window函数,假设您在过去十年中使用的是SQL Server版本。您需要将其封装在CTE中,因为Window函数仅在SELECT
和ORDER BY
子句中可用:
;WITH MyCTE AS
(
SELECT
UserId
StartDateTime,
StatusKey,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY StartDateTime) AS row_num
FROM
dbo.AgentActivityLog
WHERE
StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12'
)
SELECT
UserId,
StartDateTime,
StatusKey
FROM
MyCTE
WHERE
row_num = 1
或者,您可以使用子查询:
SELECT
L.UserId,
L.StartDateTime,
L.StatusKey
FROM
dbo.AgentActivityLog L
INNER JOIN
(
SELECT UserId, MAX(StartDateTime) AS MaxStartDateTime
FROM dbo.AgentActivityLog
WHERE StatusDateTime BETWEEN '2/9/2016 00:00:00' AND '2/9/2016 08:52:12'
GROUP BY UserId
) SQ ON
SQ.MaxStartDateTime = L.StartDateTime AND
SQ.UserId = L.UserId
这两种方法都假定您对给定StartDateTime
的{{1}}值没有完全重复。
此外,您应该避免使用UserId
(或任何列号)并使用实际的列/表达式。使用序数值是一种坏习惯,通常会导致代码出现错误和/或维护问题。