在单独的字段中使用年,月和日之间创建查询

时间:2013-07-16 20:59:43

标签: sql postgresql between

我在Postgresql的不同字段中拥有一个包含年,月和日的表,但是我需要使用'between'这些字段进行查询。我尝试了一些疯狂的事情,但没有任何效果......有谁知道帮帮我?

前表:

CREATE TABLE my_table
(
  id serial NOT NULL,
  day integer NOT NULL,
  month integer NOT NULL,
  year integer NOT NULL,
)

4 个答案:

答案 0 :(得分:8)

作弊。您没有验证这些“日期”,您只是对它们进行排序。验证是一项单独的任务,唯一合理的解决方案是架构更改。

CREATE INDEX my_table__date__idx ON test1 (year * 10000 + month * 100 + day);

SELECT *
FROM my_table
WHERE year * 10000 + month * 100 + day BETWEEN 20130101 AND 20131231;

如果您不想要存在巨大差距,请使用year*12*31 + month*31 + day

答案 1 :(得分:7)

对黑暗面的帮助

如果您对设计感到困惑,那么这应该比目前提出的任何解决方案更简单,更快 ad-hoc行类型

SELECT *
FROM   tbl
WHERE (year, month, day) BETWEEN (2013,7,3)
                             AND (2013,7,5);

->SQLfiddle demo

正义之路

但是,实际上,您应该先使用正确的表格设计。将日期保存为date,而不是三个integer列。

CREATE TABLE tbl (
  tbl_id  serial PRIMARY KEY
 ,thedate date NOT NULL
)

thedate包含所有三列:daymonthyear,需要4个字节,如integer

然后你的工作将是微不足道的:
要获取日,月,年,或周等,请使用to_char()extract()date_trunc()。这些功能非常快速且通用。

例如,您可以create a VIEW看起来完全,就像您现在拥有的表一样:

CREATE view old_table AS
SELECT tbl_id
      ,EXTRACT(day   FROM thedate)::int AS day
      ,EXTRACT(month FROM thedate)::int AS month
      ,EXTRACT(year  FROM thedate)::int AS year
FROM   my_table;

至少和你的桌子一样快,因为来源较小。

答案 2 :(得分:2)

如果您无法更改表格结构以使用正确的日期,您可以从字段中创建日期以进行比较,例如:

SELECT *
FROM Table
WHERE to_date(Year||' '||Day||' '||Month, 'YYYY DD MM') BETWEEN date1 AND date2

如果它们都是整数,则必须将每个转换为字符串,我相信::VARCHAR()有效,或CAST()

SELECT *
FROM Table
WHERE to_date(Year::varchar(4)||' '||Day::varchar(2)||' '||Month::varchar(2), 'YYYY DD MM') BETWEEN date1 AND date2

答案 3 :(得分:1)

WHERE
  (
       ((day >= :first_day) AND (month  = :first_month) AND (year  = :first_year))
    OR (                        (month >  :first_month) AND (year  = :first_year))
    OR (                                                    (year >  :first_year))
  )
  AND
  (
       ((day <= :final_day) AND (month  = :final_month) AND (year  = :final_year))
    OR (                        (month <  :final_month) AND (year  = :final_year))
    OR (                                                    (year <  :final_year))
  )

真的 会破坏搜索索引的任何机会。您可能每次都会扫描整个表格。

如果想要使用真实的日期字段,你会好一百万倍。

我永远不想发布上面的代码,更不用说有同行评审了。我感到羞愧。