PostGreSql ISNULL或子查询中的合并

时间:2018-08-01 11:08:59

标签: sql postgresql

好吧,我有一个带有时间戳列的表。我必须从该表返回所有记录,其中时间戳在给定时间点(= 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)?

2 个答案:

答案 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
                        );

您还将注意到,我在子查询中添加了表别名和限定的列名。这是避免使用子查询时出现问题的最佳实践。