postgres SQL的异常[负日期间隔和仅在条件子句中不起作用的别名]

时间:2016-05-01 18:37:40

标签: sql postgresql

我带着两个小怪物来找你们,我似乎无法理解postgres:

(1)

  SELECT "LASTREQUESTED", 
         (DATE_TRUNC('seconds', CURRENT_TIMESTAMP - "LASTREQUESTED") 
              - INTERVAL '8 hours') AS "TIME"
    FROM "USER" AS u 
    JOIN "REQUESTLOG" AS r ON u."ID" = r."ID" 
ORDER BY "TIME"

result

我正在计算用户何时可以[每8小时一次]发出下一个请求,但如果你查看第16条,我会得到“1天-06:20:47”而不是“18:00:00”ish ,不像其他每一行。 [表LASTREQUESTED是一个简单的时间戳,这里与第16行的其他条目没什么不同,为什么会这样?

(2)

在同一个请求中,如果我尝试在“TIME”列上添加一个条件,编译器会说它不存在,尽管使用它来排序是正常的。我不明白为什么。

   SELECT (DATE_TRUNC('seconds', CURRENT_TIMESTAMP - "LASTREQUESTED") 
               - INTERVAL '8 hours') AS "TIME" 
     FROM "USER" AS u 
     JOIN "REQUESTLOG" AS r ON u."ID" = r."ID" 
    WHERE "TIME" > 0 
 ORDER BY "TIME";

2 个答案:

答案 0 :(得分:1)

问题#1:负数小时但是正数天?

根据PostgreSQL documentation,这是PostgreSQL与SQL标准不同的情况:

  

根据SQL标准,间隔值的所有字段必须具有相同的符号.... PostgreSQL允许字段有不同的符号......

     

内部间隔值存储为月,日和秒。这样做是因为一个月中的天数变化,如果涉及夏令时调整,则一天可以有23或25小时。月份和日期字段是整数,而秒字段可以存储分数。 ...

您可以使用以下查询查看更极端的示例:

=# select interval '1 day' - interval '300 hours';
     ?column?     
------------------
 1 day -300:00:00
(1 row)

所以这不是以奇怪方式表达的单个秒数;相反,它是0个月,+ 1天和-1,080,000.0秒的间隔。如果您确定从这些时间间隔开始的时间戳没有夏令时问题,您可以使用justify_hours将天数转换为24小时制,并获得更有意义的间隔:

=# select justify_hours(interval '1 day' - interval '300 hours');
   justify_hours    
--------------------
 -11 days -12:00:00

问题#2:SELECT中无法使用WHERE列?

这是标准的PostgreSQL行为。见this duplicate question。在那里提出的解决方案包括:

  • 重复两次表达式,一次在SELECT列表中,再次在WHERE子句中。 (我这样做的次数比想要记住的要多......)

    SELECT (my - big * expression) AS x
    FROM stuff
    WHERE (my - big * expression) > 5
    ORDER BY x
    
  • 创建没有WHERE过滤器的子查询,并将WHERE条件放在外部查询中

    SELECT *
    FROM (SELECT (my - big * expression) AS x
          FROM stuff) AS subquery
    WHERE x > 5
    ORDER BY x
    
  • 使用WITH语句来实现类似于子查询技巧的内容。

答案 1 :(得分:0)

我现在不知道为什么它按原样计算(可能是因为你从另一个Interval中减去一个Interval)但是当你将计算更改为Timestamp减去Timestamp时它按预期工作:

DATE_TRUNC('seconds', CURRENT_TIMESTAMP - (LASTREQUESTED + INTERVAL '8 hours'))

请参阅Fiddle

关于#2:基于标准SQL,选择列表中的列是在FROM / WHERE / GROUP BY / HAVING之后计算的,但在ORDER之前,这就是为什么你不能在WHERE中使用别名的原因。有一些good articles on that topic由Itzik Ben-Gan编写(基于MS SQL Server,但类似于PostgreSQL)。