如何在 PostgreSQL 中选择某一年之后的日期
Posted
技术标签:
【中文标题】如何在 PostgreSQL 中选择某一年之后的日期【英文标题】:How to choose dates after a certain year in PostgreSQL 【发布时间】:2015-02-04 23:56:10 【问题描述】:简而言之,当我执行以下 SQL 命令时:
SELECT EXTRACT(YEAR FROM pub_date) AS year FROM news_stories
我得到了一份从 2008 年到 2014 年的大名单。
如果我这样做了
SELECT EXTRACT(YEAR FROM pub_date) AS year FROM news_stories WHERE year > 2010
我得到一个空的结果。我做错了什么?
【问题讨论】:
【参考方案1】:输出列在ORDER BY
或GROUP BY
子句中可见,因为它们是在SELECT
子句中评估表达式之后应用的。它们在 WHERE
或 HAVING
子句中不可见。所以你不能引用 output 列名year
。您必须根据 input 列重复表达式。显然,有一个同名的输入列,否则你会得到一个异常。详情:
为了让您的查询快速,您应该使用 sargable 谓词:
SELECT EXTRACT(YEAR FROM pub_date) AS year
FROM news_stories
WHERE pub_date >= '2010-1-1'::date;
这通常更快,因为 Postgres 可以直接将 pub_date
中的值与给定值进行比较,而无需先从每一行中提取年份。
更重要的是,可以通过这种方式使用 pub_date
上的普通索引 - 如果 Postgres 期望该路由更快(仅索引扫描或足够选择性)。
【讨论】:
所以我从中得到的 tl;dr 是 "WHERE pub_date >= '2010-1-1'::date" 比 "WHERE EXTRACT(YEAR FROM pub_date) > 2010" 快吗?我刚刚做了一些 AB 速度测试,并没有看到任何变化(脚本在任何一种情况下都需要 3-5 秒才能运行)……但如果你说最好采用 sargable 方法,我很好。 :-) 谢谢! @DanGoodspeed:当您选择表的一小部分或 pg 可以使用仅索引扫描 (example )。当必须读取表的大部分内容时,pg 将使用顺序扫描,您几乎看不出有什么不同。无论哪种方式,3-5 秒似乎非常长。你的桌子很大吗?你如何测量?你的pg是什么版本?我会使用EXPLAIN ANALYZE
进行测试。您不想在测试中包含网络开销。
这是一个非常不科学的测试。这是一个 perl 脚本,它执行一些通过网络运行的数据库调用(这是其中之一),我只是为页面加载计时。【参考方案2】:
您必须在数据库中有一个名为year
的列,否则SQL 将返回错误。您不能在定义别名的select
或where
子句中使用别名。
要么使用子查询,要么重复表达式:
SELECT EXTRACT(YEAR FROM pub_date) AS year
FROM news_stories
WHERE EXTRACT(YEAR FROM pub_date) > 2010;
或作为子查询:
select *
from (SELECT EXTRACT(YEAR FROM pub_date) AS year
FROM news_stories
) n
where year > 2010;
【讨论】:
【参考方案3】:试试这个。您不能在 where 子句中使用alias name
in。 WHERE clause
在 SELECT clause(*)
之前处理。由于您有名为 Year
的列,因此您没有收到错误。
SELECT EXTRACT(YEAR FROM pub_date) AS year
FROM news_stories
WHERE EXTRACT(YEAR FROM pub_date) > 2010
【讨论】:
谢谢。我认为 AS 的主要目的之一是能够缩短其中一些 SQL 语句,就像我编写它的方式一样。 @DanGoodspeed ALIASES 可用于为列或表创建一个临时名称。如果您想在where Clause
中使用别名,请查看 Gordan 答案。以上是关于如何在 PostgreSQL 中选择某一年之后的日期的主要内容,如果未能解决你的问题,请参考以下文章