繁体   English   中英

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

[英]Creating queries using between for year, month and day in separate fields

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

防爆表:

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

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

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

为黑暗面提供帮助

如果您坚持使用您的设计,这应该比目前提出的任何解决方案更简单,更快ad-hoc行类型

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

- > SQLfiddle演示

正义的道路

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

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

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

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

例如,您可以创建一个看起来与您现在的表完全相同 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;

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

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

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
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))
  )

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

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

我永远不想发布上面的代码,没关系有同行评审它。 我会感到羞愧。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM