【问题标题】:SQL Finding most recent record by groupSQL 按组查找最近的记录
【发布时间】:2016-03-14 16:11:40
【问题描述】:

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

表:【批准】 +--------------------------------------+------+-- --------------+--------------+ |身份证 |状态 |用户名 |日期戳 | +--------------------------------------+------+-- --------------+--------------+ | 63DDD358-EF3B-4355-8251-00CDE8560B3E | 5 |用户1 | 2014-12-09 11:53:40.423 | | 63DDD358-EF3B-4355-8251-00CDE8560B3E | 10 |用户1 | 2014-12-09 11:53:40.423 | | 13F65DDC-73D8-48BB-87F4-0207DE47A6D9 | 5 |用户2 | 2016-02-19 11:10:56.820 | | 13F65DDC-73D8-48BB-87F4-0207DE47A6D9 | 10 |用户3 | 2016-02-19 11:10:56.820 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 5 |用户1 | 2014-09-18 14:53:07.973 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 20 |用户3 | 2014-09-18 14:56:07.177 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 60 |用户1 | 2014-09-18 14:53:07.973 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 70 |用户1 | 2014-09-18 14:56:08.177 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 70 |用户1 | 2014-10-15 15:17:49.210 | | 5AB3C39E-8E2E-4935-BC6C-0226F444D7F2 | 90 |系统 | 2014-10-15 15:17:50.210 | +--------------------------------------+------+-- --------------+--------------+

状态码都表示审批级别,90是完成,99是取消。

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

到目前为止,我有这个查询:

SELECT a.ID,a.Status,a.ApproverID,A.DateTime FROM Approval a 内部联接 ( SELECT MAX(DateTime) as MaxDate, Status FROM Approval WHERE 状态不在 (90,99) 按状态分组 ) a1 ON a1.MaxDate = a.DateTime 和 a1.Status = a.Status

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

谁能发现我哪里出错了?

【问题讨论】:

  • 预期的结果是什么?

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


【解决方案1】:
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

【讨论】:

    【解决方案2】:

    你可以使用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 分区的top 行:如果此行的值是9099,则过滤掉整个分区。

    如果您想及时过滤掉具有9099 值的ID 分区anywhere,请使用以下查询:

    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
    

    【讨论】:

    • 您好 Giorgos,感谢您的建议,我不知道 FIRST_VALUE 函数。在这种情况下,我使用的是 SQL Server 2008,但请记住这一点以供将来参考
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-07
    • 2022-01-09
    • 2012-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多