如何生成可移动节日的日历?

时间:2013-05-21 12:41:22

标签: sql postgresql postgresql-9.2

有一张桌子:日期存储在smallint字段中的节日(不是很优雅,我知道..)。 它看起来像是:

id - serial, PK
day - smallint NOT NULL,
month - smallint NOT NULL,
year - smallint

看起来很简单 - 如果有某个日期的记录,那个日期也会有某种盛宴。

“只有”一件事让整个想法变得复杂...... Field'ear'可以为空。如果'year'为null,那意味着当天有可移动的盛宴 - 与年份无关。 (当然我可以为date创建一个字段,并且一些布尔标志'is_movable',但它不会改变我的问题中的任何内容。)

我想创建一个程序来列出指定日期范围内的所有节日。

get_all_feasts(date_from date, date_to date)

..返回表:id,date,is_movable。

例如,对于数据:

id / day / month / year
1 / 12 / 05 / 2013
2 / 15 / 05 / 2013
3 / 16 / 02 / 2012
4 / 25 / 12 / NULL
5 / 26 / 12 / NULL
6 / 2 / 04 / 2014

..函数调用:get_all_feasts('2012-03-01':: date,'2014-05-01':: date) 应该回来:

id / date
4 / 2012-12-25
5 / 2012-12-26
1 / 2013-05-12
2 / 2013-05-15
4 / 2013-12-25
5 / 2013-12-26
6 / 2014-04-02

选择指定年份,月份和日期的节日没有问题。

但是如何为特定范围内的可移动节日生成节日?

我使用PostgreSQL v.9.2。

2 个答案:

答案 0 :(得分:0)

您可以使用WITH RECURSIVE查询 - Reference

试试这个 -

WITH RECURSIVE year_table(n) AS (
    SELECT 1000
  UNION ALL
    SELECT n+1 FROM year_table
)
SELECT Id, To_Date(DAY || ' ' || MONTH || ' ' || YEAR, 'DD MM YYYY')
  FROM Feasts
 WHERE To_Date(DAY || ' ' || MONTH || ' ' || YEAR, 'DD MM YYYY') >=
       Date_From
   AND To_Date(DAY || ' ' || MONTH || ' ' || YEAR, 'DD MM YYYY') <= Date_To
   AND YEAR IS NOT NULL
UNION
SELECT Feasts.Id,
       To_Date(DAY || ' ' || MONTH || ' ' || Year_Table.n, 'DD MM YYYY')
  FROM Feasts, Year_Table
 WHERE n >= To_Char(Date_From, 'YYYY')
   AND n <= To_Char(Date_To, 'YYYY')
   AND Feasts.YEAR IS NULL;

答案 1 :(得分:0)

SELECT 
    id, (coalesce(year, EXTRACT(YEAR FROM NOW())) || '-' || month || '-' || day) as date
FROM
    feasts
WHERE 
    (coalesce(year, EXTRACT(YEAR FROM NOW())) || '-' || month || '-' || day)::date >= date_from
    AND (coalesce(year, EXTRACT(YEAR FROM NOW())) || '-' || month || '-' || day)::date <= date_to
ORDER BY
    (coalesce(year, EXTRACT(YEAR FROM NOW())) || '-' || month || '-' || day)::date, id;