我需要为每个日期获取 2 条时间最接近某个定义时间的记录
比如这是表格(真实表格数据较多)
CREATE TABLE t1 (time DATE, some_data NUMBER);
那个表会有这样的记录
INSERT INTO t1 VALUES(TO_DATE('1.1.2024 08:08:08', 'dd.mm.yyyy hh24:mi:ss'), 1);
INSERT INTO t1 VALUES(TO_DATE('1.1.2024 10:10:10', 'dd.mm.yyyy hh24:mi:ss'), 2);
INSERT INTO t1 VALUES(TO_DATE('1.1.2024 15:15:15', 'dd.mm.yyyy hh24:mi:ss'), 3);
INSERT INTO t1 VALUES(TO_DATE('1.1.2024 20:20:20', 'dd.mm.yyyy hh24:mi:ss'), 4);
INSERT INTO t1 VALUES(TO_DATE('2.1.2024 09:09:09', 'dd.mm.yyyy hh24:mi:ss'), 5);
INSERT INTO t1 VALUES(TO_DATE('2.1.2024 12:12:12', 'dd.mm.yyyy hh24:mi:ss'), 6);
INSERT INTO t1 VALUES(TO_DATE('2.1.2024 16:16:16', 'dd.mm.yyyy hh24:mi:ss'), 7);
我想为每个日期获取 2 条记录,第一个最接近 8 小时,第二个最接近 20 小时。在此示例中,结果数据将是
1.1.2024 08:08:08 1
1.1.2024 20:20:20 4
2.1.2024 09:09:09 5
2.1.2024 16:16:16 7
我尝试使用子查询来做到这一点,但由于我的实际用法有复杂的查询(带有连接、子选择等),所以我很快就迷失了。
有什么好的、干净的方法来实现这一点吗?
先谢谢你了
您可以算出每个时间与当天 08:00 和 20:00 之间的差异:
trunc(t1.time) + interval '8' hour - time
trunc(t1.time) + interval '20' hour - time
可以是正数也可以是负数,所以然后得到绝对值:
abs(trunc(t1.time) + interval '8' hour - time)
abs(trunc(t1.time) + interval '20' hour - time)
然后按每天的顺序排列:
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '8' hour - time))
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '20' hour - time))
这给你:
select t1.time, t1.some_data,
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '8' hour - time)) as rnk8,
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '20' hour - time)) as rnk20
from t1
时间 | 一些数据 | RNK8 | RNK20 |
---|---|---|---|
2024-01-01 08:08:08 | 1 | 1 | 4 |
2024-01-01 10:10:10 | 2 | 2 | 3 |
2024-01-01 15:15:15 | 3 | 3 | 2 |
2024-01-01 20:20:20 | 4 | 4 | 1 |
2024-01-02 09:09:09 | 5 | 1 | 3 |
2024-01-02 12:12:12 | 6 | 2 | 2 |
2024-01-02 16:16:16 | 7 | 3 | 1 |
最后只选择那些排名最高的行:
select time, some_data
from (
select t1.time, t1.some_data,
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '8' hour - time)) as rnk8,
rank() over (partition by trunc(time)
order by abs(trunc(t1.time) + interval '20' hour - time)) as rnk20
from t1
)
where rnk8 = 1
or rnk20 = 1
order by time
时间 | 一些数据 |
---|---|
2024-01-01 08:08:08 | 1 |
2024-01-01 20:20:20 | 4 |
2024-01-02 09:09:09 | 5 |
2024-01-02 16:16:16 | 7 |
如果您有两行具有相同(绝对)差异,那么您将看到两行。如果您不希望这种情况发生,那么您需要通过添加排序条件(例如非绝对值差异,然后可能是其他列)来决定如何打破平局。