2015-08-03 92 views
3

我正在創建一個訂閱管理系統,並且需要生成未來2年即將開票日期的列表。我已經能夠使用generate_series能得到相應的日期爲這樣:Postgres generate_series排除日期範圍

SELECT i::DATE 
FROM generate_series('2015-08-01', '2017-08-01', '1 month'::INTERVAL) i 

最後一步我需要從計算中排除特定的日期範圍。這些排除的日期範圍可以是任何時間範圍。此外,不應將它們考慮到generate_series的時間範圍內。

例如,假設我們將日期範圍從'2015-08-27'排除在'2015-09-03'之外。得到的generate_series應排除日當週從計算,基本上推動所有未來一個月結算1週日期未來

2015-08-01 
2015-09-10 
2015-10-10 
2015-11-10 
2015-12-10 
+0

刪除答案,沒有解決真正困難的部分。排除範圍很容易。困難的部分是調整它重複發生的模式,在最後增加更多時間來補償跳過的時間範圍,然後調整重複日期。你將需要一個遞歸CTE或一個過程來做到這一點我認爲,因爲通過補償排除在最後補充的行本身可以被排除,所以我們必須擴展更多的行來測試... –

+1

I也有感覺你的每月賬單結合不好,允許在幾天或幾周範圍內排除,因爲不是每個月都是相同的天數。您可能需要考慮每30天結算,而不是每個月。 –

+1

你的例子看起來是錯誤的。日期提前9天,但時間間隔只有7天。 –

回答

0

你將不得不拆分調用生成排除系列。有些事情是這樣的:

  • 的3聯合查詢
  • 首先查詢拉日期從開始到排除範圍從
  • 第二個查詢拉排除範圍和結束日期之間的日期
  • 第三個查詢拉日期當您的所有系列日期都不包含排除範圍

注意:您仍然需要通過排除列表(如果有)進行循環的方式。而且這個查詢可能不是非常有效,因爲這樣的場景可以通過函數或程序代碼更好地處理。

1

首先創建一個時間序列的日期在未來的兩年內,EXCEPT您的日期限制:

SELECT dt 
FROM generate_series('2015-08-01'::date, '2017-08-01'::date, interval '1 day') AS s(dt) 
EXCEPT 
SELECT dt 
FROM generate_series('2015-08-27'::date, '2015-09-03'::date, interval '1 day') as ex1(dt) 

注意,因爲你需要,你可以有很多EXCEPT條款。對於單個停電日(與範圍相反),您可以使用VALUES子句而不是SELECT

然後你的窗口在這段時間序列生成的計費天行號:

SELECT row_number() OVER (ORDER BY dt) AS rn, dt 
FROM (<query above>) x 

然後選擇那些日子裏要賬:

SELECT dt 
FROM (<query above>) y 
WHERE rn % 30 = 1; -- billing on the first day of the period 

(後者查詢以下克雷格的建議30天計費)

產量:

SELECT dt 
FROM (
    SELECT row_number() OVER (ORDER BY dt) AS rn, dt 
    FROM (
    SELECT dt 
    FROM generate_series('2015-08-01'::date, '2017-08-01'::date, interval '1 day') AS s(dt) 
    EXCEPT 
    SELECT dt 
    FROM generate_series('2015-08-27'::date, '2015-09-03'::date, interval '1 day') as ex1(dt) 
) x 
) y 
WHERE rn % 30 = 1;