按日期范围(同月,日)跨年过滤器(Filter by date range (same month

2019-06-27 01:10发布

我有一个表保存日期的PostgreSQL数据库。 现在,我需要找到日期范围内的所有行15/0221/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

Answer 1:

假设你想在今年一年中,无论某些天之间的日期(例如,如果你发送了一批的生日卡或某事)(与信仰的飞跃),你可以设置这个测试:

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)


Answer 2:

使用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

如果没有帮助,请扩展您的问题有:

  • 您正在使用的表(S)的结构,无论是从psql的\d tablename命令或原始CREATE TABLE语句;
  • 一些样本内容
  • 你有问题查询
  • 预期成绩


Answer 3:

您可以使用下面的语法。

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 

当进入这两个日期,仔细检查上面的例子。 输入相同的格式,并且附上他们内部的''秒。

如果您要更换*标记与列名,您可以过滤出列的值。

希望帮助..



Answer 4:

我敢肯定,这个问题的@ 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毫秒
字符串比较是与“非现场”更快C -更多在大约核对支持手动 。

SELECT * FROM tbl
WHERE  EXTRACT(MONTH FROM data)*100 + EXTRACT(DAY FROM data)
       BETWEEN 215 AND 621;

总运行时间:209.965毫秒

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毫秒

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毫秒

@凯文与排构造的解决方案:

SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data))
       BETWEEN (2, 15) AND (6, 21);

总运行时间:125.460毫秒
起首。


功能性索引快

击败唯一的方法是使用索引。 查询的无上述可以使用一个普通的索引data 。 但是,如果读取性能是至关重要的(并在写入性能一部小成本),你可以再打一个函数索引 :

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毫秒

而这也正是我终于可以用吹风击败了凯文的查询:与单个列的索引,而不是在他的案件所需要的多列索引。

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毫秒



Answer 5:

您可以使用简单的条件> =和<=或类似的或使用之间/和,但关键是要知道你的确切数据类型。 有时日期字段包含时间,这正是因此建议使用一些最新相关功能排除时间问题,查询可能会出错。 在SQL Server公共功能要做到这一点是DATEDIFF函数。



文章来源: Filter by date range (same month and day) across years