如何根据具有最后时间戳的行筛选 SQL 结果?

How Can I Filter SQL Results Based On Row With Last Timestamp?

我是 SQL 的新手;请原谅这个问题的幼稚

假设您有一个 table,其中每一行都有以下条目,所有条目都是 varchar(50):DocumentName、DocumentNumber、Status、PreviousUser、NextUser、Timestamp。时间戳使得字母排序也是按时间顺序排列的。虽然每一行都是唯一的,但不能保证每一行的 DocumentName 和 DocumentNumber 条目都是唯一的。

我想对 returns unique DocumentName、DocumentNumber 和 Status last 该 DocumentName 和 DocumentNumber 的 NextUser 条目(按时间戳测量)与我拥有的字符串匹配。我如何将其格式化为查询?

这是一个示例 table,其中包含示例 returns,可能有助于阐明我的要求。

+================+================+============+==============+==========+============+
| DocumentName   | DocumentNumber | Status     | PreviousUser | NextUser | Timestamp  |
+================+================+============+==============+==========+============+
| Change Request | 1              | PROCESSING | SSMITH       | MJONES   | 2020 02 01 |
+----------------+----------------+------------+--------------+----------+------------+
| Change Request | 1              | DRAFT      | JDOE         | SSMITH   | 2020 01 01 |
+----------------+----------------+------------+--------------+----------+------------+
| Change Request | 1              | COMPLETE   | SSMITH       | NULL     | 2020 02 22 |
+----------------+----------------+------------+--------------+----------+------------+
| Change Request | 1              | APPROVAL   | MJONES       | SSMITH   | 2020 02 21 |
+----------------+----------------+------------+--------------+----------+------------+
| Change Request | 3              | PROCESSING | JDOE         | SSMITH   | 2020 04 17 |
+----------------+----------------+------------+--------------+----------+------------+
| User Request   | 1              | APPROVAL   | SSMITH       | MJONES   | 2020 01 01 |
+----------------+----------------+------------+--------------+----------+------------+
| User Request   | 1              | REWORK     | MJONES       | SSMITH   | 2020 03 03 |
+----------------+----------------+------------+--------------+----------+------------+
| User Request   | 1              | APPROVAL   | SSMITH       | MJONES   | 2020 03 07 |
+----------------+----------------+------------+--------------+----------+------------+
| User Request   | 7              | DRAFT      | JDOE         | SSMITH   | 2020 03 17 |
+----------------+----------------+------------+--------------+----------+------------+
| User Request   | 7              | APPROVAL   | SSMITH       | MJONES   | 2020 03 19 |
+----------------+----------------+------------+--------------+----------+------------+
| Problem Report | 1              | PROCESSING | JDOE         | SSMITH   | 2020 05 03 |
+----------------+----------------+------------+--------------+----------+------------+
| Problem Report | 1              | DRAFT      | JDOE         | JDOE     | 2020 05 02 |
+----------------+----------------+------------+--------------+----------+------------+
| Problem Report | 9              | COMPLETE   | JDOE         | NULL     | 2020 06 24 |
+----------------+----------------+------------+--------------+----------+------------+
| Problem Report | 13             | DRAFT      | JDOE         | SSMITH   | 2020 07 04 |
+----------------+----------------+------------+--------------+----------+------------+
| Problem Report | 13             | REWORK     | SSMITH       | JDOE     | 2020 07 17 |
+----------------+----------------+------------+--------------+----------+------------+

如果我想匹配JDOE,我应该返回一行:('Problem Report', 13).

如果我想匹配 SSMITH,我应该返回两行:('Change Request', 3) 和 ('Problem Report', 1).

如果我想匹配 MJONES,我应该返回两行:('User Request', 1) 和 ('User Request', 7).

如果我有什么不明确的地方,请告诉我。

这有帮助吗?

Select DISTINCT DocumentName, DocumentNumber, Status
from table_name
WHERE nextuser = 'your string'
  AND timestamp = (Select MAX(timestamp) from table_name)

您可以使用 window 函数根据文档名称、文档编号和状态对条目进行排名,如下所示:

  SELECT
    docName,
    docNumber,
    status,
    prevU,
    nextU,
    ts,
    RANK() OVER (
      PARTITION BY
        docName,
        docNumber,
        status
      ORDER BY
        ts desc
    ) rnk
 FROM docs

基本上这是针对每个 docName、docNumber 和状态所做的,它将 return 基于最近日期的排名。例如,根据您的示例数据,您有四次 'Change Request' 且 docNumber 为“1”,每次都有不同的状态。由于这 4 个整体的状态是唯一的,因此它们排名为 1。对于“用户请求”docNumber“1”和状态 'APPROVAL' 出现两次,您将看到排名为“2020-03-07”的日期为 1,因为这是最近的。

样本结果可以在这个dbfiddle中找到。您可以修改它以包含所有示例数据,以便更好地了解排名的工作原理。

获得完整结果后,您可以按以下过滤条件进行查询:

 where rnk = 1 and nextU = 'name'

上述过滤器将 return 该特定用户的最新条目。 Example

此外,请注意,我刚刚更改了示例中的列名称,以方便我使用。

另外,我不完全确定你需要如何分区,所以你可以根据你的要求修改它。

如果它只需要基于 docName 和 docNumber,则只需从 partition by 子句中删除状态列。 scenario

的结果

在您提供 table 名称后尝试此操作:

SELECT *
FROM Abc123 AS a
WHERE NextUser = @MyUser
AND 
EXISTS 
(
   SELECT 1
   FROM abc123 AS i
   WHERE a.DocumentName = i.DocumentName
   AND a.DocumentNumber = i.DocumentNumber
   GROUP BY i.DocumentName,
       i.DocumentNumber
   HAVING MAX(i.Timestamp) = a.Timestamp
)

这应该 return 来自 table 的记录,其中最后一个触摸该记录的 NextUser 与 @MyUser 匹配。

内部查询确定每个文档名称和文档编号的最大时间戳。然后,外部查询通过名称、编号和时间戳进行关联。最后根据你的参数过滤外层查询结果

这应该是可搜索的,并且也可以与 table 上的任何相关索引一起使用。