SQL按组查找最近的记录

时间:2016-03-14 07:30:51

标签: sql sql-server grouping greatest-n-per-group

我的工作流应用程序的批准历史记录表包含以下带有一些垃圾数据的结构:


Table: [Approval]
+--------------------------------------+-------+----------------+-------------------------+
| ID                                   |Status | UserID         | DateStamp               |
+--------------------------------------+-------+----------------+-------------------------+
| 63DDD358-EF3B-4355-8251-00CDE8560B3E | 5     |User1           | 2014-12-09 11:53:40.423 |
| 63DDD358-EF3B-4355-8251-00CDE8560B3E | 10    |User1           | 2014-12-09 11:53:40.423 |
| 13F65DDC-73D8-48BB-87F4-0207DE47A6D9 | 5     |User2           | 2016-02-19 11:10:56.820 |
| 13F65DDC-73D8-48BB-87F4-0207DE47A6D9 | 10    |User3           | 2016-02-19 11:10:56.820 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 5     |User1           | 2014-09-18 14:53:07.973 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 20    |User3           | 2014-09-18 14:56:07.177 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 60    |User1           | 2014-09-18 14:53:07.973 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 70    |User1           | 2014-09-18 14:56:08.177 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 70    |User1           | 2014-10-15 15:17:49.210 |
| 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 90    | System         | 2014-10-15 15:17:50.210 |
+--------------------------------------+-------+----------------+-------------------------+

状态代码均表示批准级别,90表示完成,取消为99.

我需要通过在分组数据时找到顶行来查找尚未完成或取消的等待批准的请求。然后,这将用于发送提醒用户具有未完成批准的电子邮件

到目前为止,我有这个问题:


SELECT a.ID,a.Status,a.ApproverID,A.DateTime FROM Approval a
INNER JOIN 
    (
    SELECT MAX(DateTime) as MaxDate, Status FROM Approval
    WHERE Status not in (90,99)
    GROUP BY Status
    ) a1 ON a1.MaxDate = a.DateTime and a1.Status = a.Status

这会对数据进行分组并为我提供最新记录,但不会忽略任何已完成或取消的记录。

有人可以找到我出错的地方吗?

2 个答案:

答案 0 :(得分:2)

SELECT *
FROM
(
SELECT a.ID,a.Status,a.ApproverID,A.DateTime, 
       RN = ROW_NUMBER() OVER (PARTITION BY a.ID ORDER BY A.DateTime DESC)
FROM   Approval a
WHERE  NOT EXISTS
       (
           SELECT *
           FROM   Approval x
           WHERE  x.ID = a.ID
           AND    x.Status in (90, 99)
       )
) A
WHERE A.RN = 1

RN = 1将按ID提供最新记录

NOT EXISTS()是排除具有90或99状态的ID

答案 1 :(得分:0)

您可以使用FIRST_VALUE

SELECT ID, Status, UserID, DateStamp
FROM (
  SELECT ID, Status, UserID, DateStamp,
         FIRST_VALUE(Status) OVER (PARTITION BY ID 
                                   ORDER BY DateStamp DESC) AS last_status
  FROM Approval) AS t
WHERE  last_status NOT IN (90,99)

FIRST_VALUE返回每个ID分区的顶部行:如果此行的值为9099,那么整个分区过滤掉了。

如果您要及时过滤ID分区值9099 SELECT ID, Status, UserID, DateStamp FROM ( SELECT ID, Status, UserID, DateStamp, COUNT(CASE WHEN Status IN (90,99) THEN 1 END) OVER (PARTITION BY ID) AS cnt_status FROM Approval) AS t WHERE cnt_status = 0 分区,请使用以下查询:< / p>

{{1}}