(递归?)使用可变行数填充表,具体取决于另一个表中另一列的值

时间:2013-01-15 19:48:22

标签: sql postgresql

我有[报纸,杂志]版本的概念,每个地区都可以指定他们想要发布它们的频率。一个地区可能每月发布一次,另一个地区可能每年只发布一次。

select id, frequency from regions;
 id | frequency
----+-----------
  1 | 1 year
  2 | 6 mons
  3 | 4 mons
  4 | 1 mon

版本的名称是一个更容易翻译的日期,因为它始终是月份的名称(使用其编写的语言)和发布年份。开始/结束日期是应考虑将文章包含在版本中的参考点(还有另一个表格包含文章/版本之间的链接,因为并非所有文章都已发布)。

select region_id, name, date_start, date_end from editions;
 region_id |    name    |       date_start       |        date_end
-----------+------------+------------------------+------------------------
         1 | 2013-01-01 | 2012-03-24 00:00:00-04 | 2012-12-23 23:59:59-05
         2 | 2013-01-01 | 2012-09-24 00:00:00-04 | 2012-12-23 23:59:59-05
         3 | 2013-01-01 | 2012-11-24 00:00:00-05 | 2012-12-23 23:59:59-05
         4 | 2013-01-01 | 2013-02-24 00:00:00-05 | 2012-12-23 23:59:59-05
         2 | 2013-07-01 | 2012-12-24 00:00:00-05 | 2013-12-23 23:59:59-05
         1 | 2014-01-01 | 2012-12-24 00:00:00-05 | 2014-12-23 23:59:59-05
         4 | 2013-02-01 | 2012-12-24 00:00:00-05 | 2013-02-23 23:59:59-05
         3 | 2013-05-01 | 2012-12-24 00:00:00-05 | 2013-08-23 23:59:59-04

我有这个查询为每个区域生成 next 版本:

INSERT INTO editions
    (region_id, name, date_start, date_end)
SELECT 
    regions.id,
    (last_edition.name + regions.frequency) :: date AS name,
    last_edition.date_end + interval '1 second' AS date_start,
    last_edition.name + regions.frequency + regions.frequency - interval '1 month' + interval '22 23:59:59' AS date_end
FROM
    (SELECT region_id, max(name) :: timestamp AS name, max(date_end) AS date_end FROM editions GROUP BY region_id, date_end) AS last_edition JOIN
    regions ON regions.id = last_edition.region_id

问题在于,每次运行查询时,每个区域都会生成相同数量的版本。我正在寻找的是一个查询,如果我指定一个日期,它将生成从最新版本开始的所有版本,直到该日期为每个区域。例如,如果日期是从现在开始的一年,它将生成以下数量的版本:

  • 每个地区1个版本,频率为1 year
  • 每个地区有2个版本,频率为6 months
  • 每个地区有4个版本,频率为3 months
  • 每个地区有12个版本,频率为1 month

这种查询通常会同时通过所有区域的cron作业运行,但如果需要重新生成其版本,则可以针对特定区域运行,因为它们已经改变了它们的频率。

1 个答案:

答案 0 :(得分:2)

尝试类似:

SELECT 
    regions.id,
    name as last_name, 
    generate_series(name + frequency,'2015-01-01',frequency) as name,

    generate_series(name + frequency,'2015-01-01',frequency) 
    + frequency 
    - interval '1 month' 
    + interval '23 days' AS date_start,

    generate_series(name + frequency,'2015-01-01',frequency) 
    + 2 * frequency 
    - interval '1 month' 
    + interval '22 23:59:59' AS date_end

FROM (SELECT region_id, max(name) AS name
      FROM editions 
      GROUP BY region_id) AS last_edition 
JOIN regions ON regions.id = last_edition.region_id

ORDER BY 1, 2

生成从最近到指定日期的所有版本(例如'2015-01-01')。