我有一个PostgreSQL数据库,其中包含一个保存日期的表。
现在,我需要查找所有年份中15/02
日期范围内的所有行,直到21/06
(日/月)。
示例结果:
1840-02-28
1990-06-21
1991-02-15
1991-04-25
1992-05-30
1995-03-04
1995-04-10
2001-02-03
2010-04-06
答案 0 :(得分:7)
假设(通过信念的飞跃)你想要一年中某些日子之间的日期而不管一年(如果你发送了一批生日贺卡或其他东西),你可以设置一个测试:
CREATE TABLE d (dt date);
COPY d FROM STDIN;
1840-02-28
1990-06-21
1991-02-15
1991-04-25
1992-05-30
1995-03-04
1995-04-10
2001-02-03
2010-04-06
\.
您可以使用“行值构造函数”轻松选择所需的范围:
SELECT * FROM d
WHERE (EXTRACT(MONTH FROM dt), EXTRACT(DAY FROM dt))
BETWEEN (2, 15) AND (6, 21);
哪个收益率:
dt ------------ 1840-02-28 1990-06-21 1991-02-15 1991-04-25 1992-05-30 1995-03-04 1995-04-10 2010-04-06 (8 rows)
答案 1 :(得分:1)
对WHERE
运算符使用BETWEEN
子句。参见:
http://www.postgresql.org/docs/current/static/functions-comparison.html#FUNCTIONS-COMPARISON
和
http://www.postgresql.org/docs/current/static/sql-select.html http://www.postgresql.org/docs/current/static/tutorial.html
如果这样做无效,请使用以下方式扩展您的问题:
\d tablename
命令或原始的CREATE TABLE
语句; 答案 2 :(得分:1)
您可以使用以下语法。
SELECT * FROM tableName WHERE dateColumnName BETWEEN '2012.01.01' AND '2012.08.14';
只需替换以下内容;
tableName - Name of the table you are going to access
dateColumnName - Name of the column whch contains dates
2012.08.1 - Start date
2012.08.21 - End date
输入两个日期时,请仔细检查上面的示例。输入相同的格式,并将它们包含在''
s。
如果您使用列名替换*
标记,则只能过滤掉该列的值。
希望有所帮助..
答案 3 :(得分:1)
我很确定,@ kgrittn对这个问题的解释是准确的,我喜欢他对行构造函数的优雅使用。在我测试了几种替代方案后,情况更是如此:
使用65426行的真实表进行测试; 32107合格。 PostgreSQL 9.1.4,最好的五个EXPLAIN ANALYZE
:
SELECT * FROM tbl
WHERE to_char(data, 'MMDD') BETWEEN '0215' AND '0621';
总运行时间:251.188毫秒
SELECT * FROM tbl
WHERE to_char(data, 'MMDD')::int BETWEEN 215 AND 621;
总运行时间:250.965毫秒
SELECT * FROM tbl
WHERE to_char(data, 'MMDD') COLLATE "C" BETWEEN '0215' AND '0621';
总运行时间:221.732 ms
“非语言环境”C
的字符串比较速度更快 - the manual about collation support更多。
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data)*100 + EXTRACT(DAY FROM data)
BETWEEN 215 AND 621;
总运行时间:209.965 ms
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data) BETWEEN 3 AND 5
OR EXTRACT(MONTH FROM data) = 2 AND EXTRACT(DAY FROM data) >= 15
OR EXTRACT(MONTH FROM data) = 6 AND EXTRACT(DAY FROM data) <= 21;
总运行时间:160.169 ms
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data) BETWEEN 2 AND 6
AND CASE EXTRACT(MONTH FROM data)
WHEN 2 THEN EXTRACT(DAY FROM data) >= 15
WHEN 6 THEN EXTRACT(DAY FROM data) <=21
ELSE TRUE END;
总运行时间:147.390毫秒
SELECT * FROM tbl
WHERE CASE EXTRACT(MONTH FROM data)
WHEN 3 THEN TRUE
WHEN 4 THEN TRUE
WHEN 5 THEN TRUE
WHEN 2 THEN EXTRACT(DAY FROM data) >= 15
WHEN 6 THEN EXTRACT(DAY FROM data) <= 21
ELSE FALSE END;
总运行时间:131.907毫秒
@ Kevin的行构造函数解决方案:
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data))
BETWEEN (2, 15) AND (6, 21);
总运行时间: 125.460 ms
开头语。
击败它的唯一方法是使用索引。以上查询都不能在data
上使用普通索引。但是,如果读取性能至关重要(并且写入性能的成本很低),您可以使用functional index:
CREATE INDEX ON tbl(EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data));
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data))
BETWEEN (2, 15) AND (6, 21);
总运行时间: 85.895 ms
这就是我最终可以通过头发击败Kevin的查询:使用单列索引而不是他所需的多列索引。
CREATE INDEX ON tbl(
CAST(EXTRACT(MONTH FROM data) * 100 + EXTRACT(DAY FROM data) AS int));
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data) * 100 + EXTRACT(DAY FROM data))::int
BETWEEN 215 AND 621;
总运行时间: 84.215 ms
答案 4 :(得分:1)
您可以使用简单条件&gt; =和&lt; =或类似或在/之间使用,但技巧是知道您的确切数据类型。 有时日期字段包含时间,这是查询可能出错的地方,因此建议使用一些与日期相关的函数来消除时间问题。在SQL Server中,常见的功能就是具有约会功能。