最接近时间的记录

问题描述 投票:0回答:1

我需要为每个日期获取 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

我尝试使用子查询来做到这一点,但由于我的实际用法有复杂的查询(带有连接、子选择等),所以我很快就迷失了。
有什么好的、干净的方法来实现这一点吗?
先谢谢你了

oracle plsql
1个回答
0
投票

您可以算出每个时间与当天 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

小提琴

如果您有两行具有相同(绝对)差异,那么您将看到两行。如果您不希望这种情况发生,那么您需要通过添加排序条件(例如非绝对值差异,然后可能是其他列)来决定如何打破平局。

© www.soinside.com 2019 - 2024. All rights reserved.