首页 > 解决方案 > 筛选单列上的 SELECT 结果

问题描述

我正在使用“路线”表,该表详细说明了特定 ProductID 的一组有序“阶段”:

| ID | ProductID | StageID | Order |
|----+-----------+---------+-------|
|  0 |         1 |       4 |     1 |
|  1 |         1 |       2 |     2 |
|  2 |         1 |       3 |     3 |
|  3 |         1 |       7 |     4 |
|  4 |         1 |       5 |     5 |
|----+-----------+---------+-------|

还有一个记录表,其中详细说明了产品序列号在特定阶段的时间戳通过/失败结果:

| ID | RecordDate          | Serial Number | StageID | Result |
|----+---------------------+---------------+---------+--------|
|  0 | 2019-03-16 00:00:00 | G001          |       4 |      1 |
|  1 | 2019-03-16 00:01:00 | G001          |       2 |      1 |
|  2 | 2019-03-16 00:02:00 | G001          |       2 |      0 |
|----+---------------------+---------------+---------+--------|

从上面的假设数据可以看出,序列号 G001 已经通过了第 4 阶段,并且通过了,然后是第 2 阶段并通过了,但随后又通过了第 2 阶段并失败了。

现在,我想从该记录表中为特定的 SerialNumber 选择结果,其中 StageID 存在于该产品的 Route 中。这很容易 - 这是我的查询:

SELECT StageID, Result, RecordDate
FROM Records
WHERE StageID IN (SELECT StageID FROM Route WHERE ProductID = 1) AND SerialNumber = 'G001';

对于上述数据,这给了我:

| StageID | Result | RecordDate          |
|---------+--------+---------------------|
|       4 |      1 | 2019-03-16 00:00:00 |
|       2 |      1 | 2019-03-16 00:00:01 |
|       2 |      0 | 2019-03-16 00:00:02 |
|---------+--------+---------------------|

现在,我的 SQL 知识不幸过期的复杂一点是,我想过滤 StageID,以便只显示Records 表中该 StageID 和 SerialNumber 的最新结果。所以在给定的例子中,我想要这个:

| StageID | Result | RecordDate          |
|---------+--------+---------------------|
|       4 |      1 | 2019-03-16 00:00:00 |
|       2 |      0 | 2019-03-16 00:00:02 |
|---------+--------+---------------------|

过滤可以在 RecordDate 上完成,或者更容易在 Records.ID 上完成。

但我无法弄清楚可以实现这一点的 SQL,我认为这是我对语言的了解不够,无法清楚地表达我想要做什么的情况。

所以我的问题是:是否可以在每个 StageID 的最新记录上过滤这些结果?

我玩过 GROUP BY 选项无济于事。

标签: sqlgroup-by

解决方案


使用窗口函数:

SELECT r.StageID, r.Result, r.RecordDate
FROM (SELECT r.*
             ROW_NUMBER() OVER (PARTITION BY r.StageID ORDER BY r.RecordDate DESC) as seqnum
       FROM Records r
     ) JOIN
     Route ro
     ON ro.StageID = r.StageID AND ro.ProductId = 1
WHERE r.SerialNumber = 'G001';

或者,您可以添加

SELECT r.StageID, r.Result, r.RecordDate
FROM Records r
WHERE r.StageID IN (SELECT ro.StageID
                    FROM Route ro
                    WHERE ro.ProductID = 1
                   ) AND
      r.SerialNumber = 'G001' AND
      r.RecordDate = (SELECT MAX(r2.RecordDate)
                      FROM records r2
                      WHERE r2.StageId = r.StageId
                     );

推荐阅读