我带着两个小怪物来找你们,我似乎无法理解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"
我正在计算用户何时可以[每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";
答案 0 :(得分: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
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)。