对于A、B、C值相同的行,如何在给定时间范围内select只"earliest"行(D列指定)?

For rows with the same A, B, C values, how to select only "earliest" row (specified by column D) within a given time range?

我目前有一个查询(在下面进行了简化):

SELECT name, node, points, <bunch of other fields>,
  DATE(snapshot_date) AS snap_date,
  HOUR(snapshot_date) AS snap_hour,
  CASE
    WHEN MINUTE(snapshot_date) IN (5, 6) THEN 0
    WHEN MINUTE(snapshot_date) IN (35, 36) THEN 30
  END AS snap_mins,
from some_table
where 
  <bunch of conditions here> 

基本上,我们从中获取数据的数据源会在他们的工作完成时写入他们的时间戳 运行,而不是在数据实际进入时(我们对此无能为力) ).他们的工作通常在数据进入后 5-6 分钟结束,因此我们通过自己设置 snap_mins 来推断数据的实际分钟值。 (由于我不会深入的原因,我们只能使用半小时的值,并且需要每半小时为给定的 name/id/node 排一行。)

但是,我知道这真的很不稳定,我想尝试,而不是寻找特定的分钟值,只是抓住第一个行,其snapshot_date的分钟值介于每半小时后的 4-10 分钟之间(XX:00 或 XX:30)。例如,如果 table 看起来像这样:

| name  | node | points | ... | snapshot_date | 
| Jane  | 1    | 1      | ... | 1/1/21 22:02  |
| Jane  | 1    | 2      | ... | 1/1/21 22:05  | // take this value
| Jane  | 1    | 3      | ... | 1/1/21 22:09  |
| Jane  | 1    | 4      | ... | 1/1/21 22:38  | // take this value
| Jane  | 1    | 5      | ... | 1/1/21 22:41  |

| Jane  | 1    | 1      | ... | 1/1/21 23:05  | // take this value
| Jane  | 1    | 2      | ... | 1/1/21 23:06  |
| Jane  | 1    | 3      | ... | 1/1/21 23:35  | // take this value
| Jane  | 1    | 4      | ... | 1/1/21 23:38  |

| Jane  | 3    | 1      | ... | 1/1/21 23:02  |
| Jane  | 3    | 2      | ... | 1/1/21 23:07  | // take this value (current query wouldn't pick this up because it's only looking for snapshots where the minute value is 5 or 6) 
| Jane  | 3    | 3      | ... | 1/1/21 23:10  |
| Jane  | 3    | 4      | ... | 1/1/21 23:35  | // take this value
| Jane  | 3    | 5      | ... | 1/1/21 23:38  |

所以我想得到的查询结果是:

| name  | node | points | ... | snap_date | snap_hour | snap_mins
| Jane  | 1    | 2      | ... | 1/1/21    | 22        | 0
| Jane  | 1    | 4      | ... | 1/1/21    | 22        | 30
| Jane  | 1    | 1      | ... | 1/1/21    | 23        | 0
| Jane  | 1    | 3      | ... | 1/1/21    | 23        | 30
| Jane  | 3    | 2      | ... | 1/1/21    | 23        | 0
| Jane  | 3    | 4      | ... | 1/1/21    | 23        | 30

但是,我一直在努力确定是否有可能做到这一点。任何帮助将不胜感激!

一个选项

  1. 添加定义关联的 30 分钟间隔的列
  2. 30 分钟组内的行序号
  3. 每组只取序列#1
WITH x AS (
  SELECT name, node, points, snapshot_date, <bunch of other fields>,
  DATE(snapshot_date) AS snap_date,
  HOUR(snapshot_date) AS snap_hour,
  CASE
    WHEN MINUTE(snapshot_date) < 31 THEN 0
    ELSE 30
  END AS snap_mins
FROM some_table
where 
  <bunch of conditions here> 
), 
y as (
  SELECT x.*,
  ROW_NUMBER() OVER (PARTITION BY name, node, snap_date, snap_hour, snap_minute ORDER BY snapshot_date) AS seq
  FROM x
)
SELECT * FROM y WHERE seq = 1

如果您确实需要忽略第 0-3 分钟和第 30-33 分钟的行,请在第一个 CTE 中添加一个 WHERE 条件。