我在Postgresql的不同字段中拥有一个包含年,月和日的表,但是我需要使用'between'这些字段进行查询。我尝试了一些疯狂的事情,但没有任何效果......有谁知道帮帮我?
前表:
CREATE TABLE my_table
(
id serial NOT NULL,
day integer NOT NULL,
month integer NOT NULL,
year integer NOT NULL,
)
答案 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);
但是,实际上,您应该先使用正确的表格设计。将日期保存为date
,而不是三个integer
列。
CREATE TABLE tbl (
tbl_id serial PRIMARY KEY
,thedate date NOT NULL
)
thedate
包含所有三列:day
,month
,year
,需要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))
)
真的 会破坏搜索索引的任何机会。您可能每次都会扫描整个表格。
如果想要使用真实的日期字段,你会好一百万倍。
我永远不想发布上面的代码,更不用说有同行评审了。我感到羞愧。