好吧,我有一个带有时间戳列的表。我必须从该表返回所有记录,其中时间戳在给定时间点(= timeX)之后加上最后一条记录timeX。
我的方法是对时间戳排序的条目进行编号。然后子选择timeX(= numX)之后的第一条记录的编号。并返回所有大于numX-1的记录。
测试设置
CREATE TABLE public.events
(
id integer,
name character varying(50) COLLATE pg_catalog."default",
happens timestamp without time zone
);
INSERT INTO events (id, name, happens)
VALUES
(1, 'event 7', '2018-08-01 07:00:00.000000'),
(2, 'event 6', '2018-08-01 06:00:00.000000'),
(3, 'event 2', '2018-08-01 02:00:00.000000'),
(4, 'event 5', '2018-08-01 05:00:00.000000'),
(5, 'event 1', '2018-08-01 01:00:00.000000'),
(6, 'event 8', '2018-08-01 08:00:00.000000'),
(7, 'event 5.2', '2018-08-01 05:00:00.000000'),
(8, 'event 4', '2018-08-01 04:00:00.000000'),
(9, 'event 3', '2018-08-01 03:00:00.000000');
我当前的查询
WITH AllEvents AS (
SELECT
ROW_NUMBER() OVER (ORDER BY happens) AS num,
id,
name,
happens
FROM events
ORDER BY num
)
SELECT * FROM AllEvents ae
WHERE ae.num >=
(
SELECT Num-1
FROM AllEvents
WHERE happens >= '2018-08-01 02:30:00'
LIMIT 1
);
该查询在'2018-08-01 02:30:00'上运行良好,因为select查找了可以返回num的条目。
如果我尝试选择'2018-08-01 17:30:00',则查询未找到记录,因此返回的num为null,结果为空列表,而不是最后一条记录。
我尝试使用ISNULL或COALESCE和MAX(ae.num)修复此问题,但无法正常工作。
任何提示我都可以完成空检查并返回最后一条记录(等于Max(ae.num)?
答案 0 :(得分:1)
这不是更简单吗?:
select * from events
where happens >=
(select max(happens) from events
WHERE happens < '2018-08-01 02:30:00');
答案 1 :(得分:0)
我不太了解要实现的逻辑。因此,可能会有一种更简单的方法来完成您想要的工作。
但是,您可以将子查询作为参数来修正查询:
WHERE ae.num >= COALESCE((SELECT ae2.Num - 1
FROM AllEvents ae2
WHERE ae2.happens >= '2018-08-01 02:30:00'
LIMIT 1
), ae.num
);
您还将注意到,我在子查询中添加了表别名和限定的列名。这是避免使用子查询时出现问题的最佳实践。