共一排
SELECT *
FROM widgets
ORDER BY loaded_date_time < now()::date, loaded_date_time
LIMIT 1;
..首先有效地对今天的时间戳(+不存在的未来)进行排序,因为boolean
表达式是排序的FALSE
-> TRUE
-> NULL
。
如果未来的日期是可能的:
ORDER BY
(loaded_date_time::date = now()::date) DESC NULLS LAST
,loaded_date_time
NULLS LAST
仅当可以为 NULL 时才相关loaded_date_time
,这应该是不允许的。在这种情况下删除该子句。
每个小部件一行
SELECT DISTINCT ON (widget_id)
widget_id, loaded_date_time
FROM widgets
ORDER BY
widget_id
,(loaded_date_time::date = now()::date) DESC
,loaded_date_time;
为什么以及如何工作?
- 关于
DISTINCT ON
:
在ORDER BY
子句中......
首先widget_id
,显然 - 必须匹配DISTINCT
子句。
...然后首先对“今天”的记录进行排序。如果没有,其他记录会自动上移。
...最后,较早的记录首先排序。
因此,所需的行首先出现并由 挑选DISTINCT
。一口气全部搞定。
如果将表达式重写(loaded_date_time::date = now()::date)
为
(loaded_date_time >= now()::date AND
loaded_date_time < (now()::date + 1)) -- note: < not: <=
.. 在 . 上使用普通索引可能会更快loaded_date_time
。因为,如果等号两边都有表达式,那么你肯定根本不能使用普通索引。你应该有一个关于 widget_id 的索引(显然),可能还有一个索引loaded_date_time
:
CREATE INDEX foo_idx ON widgets (loaded_date_time)
多列索引可能会快一点:
CREATE INDEX foo_idx ON widgets (widget_id, loaded_date_time);
用 测试EXPLAIN ANLYZE
,是否被使用。应该是的,我没有测试。如果没有,那就没有意义了。