2011-05-05 168 views
0

我有給定日期範圍的以下費率表。PostgreSQL多個日期範圍的價格

我想寫一個SQL查詢(PostgreSQL的),以獲得價格的總和對於給定的時間段,如果它是一個連續period..for例如:如果我指定到2011-05-02 2011-05

-09第一組應當歸還的6行的總和,

,如果我在第二組沒有應返回指定2011-05-02至2011-05-011。

我的問題是,我不知道如何確定一個日期範圍是否連續......你能幫忙嗎?非常感謝

的情況下1:總和預計

price  from_date  to_date 
------ ------------ ------------ 
    1.0  "2011-05-02" "2011-05-02" 
    2.0  "2011-05-03" "2011-05-03" 
    3.0  "2011-05-04" "2011-05-05" 
    4.0  "2011-05-05" "2011-05-06" 
    5.0  "2011-05-06" "2011-05-07" 
    4.0  "2011-05-08" "2011-05-09" 

案例2:沒有結果預計

price  from_date  to_date 
------ ------------ ------------ 
    1.0  "2011-05-02" "2011-05-02" 
    2.0  "2011-05-03" "2011-05-03" 
    3.0  "2011-05-07" "2011-05-09" 
    4.0  "2011-05-09" "2011-05-011" 

我沒有重疊率的日期範圍。

+0

爲什麼是第一個例子不斷?價格5.0在2011-05-07結束,接下來的兩天開始兩天後? – 2011-05-05 12:14:59

+0

對不起我的壞...修正了它 – Rob 2011-05-05 12:53:41

+0

如果你在第一組中指定'2011-05-02'到'2011-05-11'怎麼辦(假設'(4.0「2011-05-08」 「2011-05-09」)')?它是否應該返回「2011-05-02」到「2011-05-09」的結果? – 2011-05-05 13:06:08

回答

0

要獲得價格的總和:

select sum(price) 
from your_table 
where .. checking to and from dates .. 
having param_dateend - param_datestart = sum(to_date - from_date) 

然而,必須保證該時段不重疊。如果他們這樣做,查詢將不會返回正確的結果。

您還需要自己計算日期檢查 - 我不確定如果enddate或startdate處於某條記錄的中間(記錄的to_date和from_date之間),應該發生什麼情況。將需要改變,如果你需要包括這樣的情況:

having param_dateend - param_datestart = sum(
    case when to_date > param_dateend then param_dateend else to_date end 
    - 
    case when from_date < param_datestart then param_datestart else from_date end 
) 
+0

非常感謝......期間不重疊......無論結束日期的持續時間是什麼時候都沒有關係......我會嘗試查詢。 – Rob 2011-05-05 12:57:53

+0

@Rob給你一個例子 - 在你的第二種情況下,你有一段「2011-05-09」「2011-05-011」'如果你的結束日期是'2011-05-10' ?您還可以在表格中使用「2011-05-05」「2011-05-011」',並尋找'2011-05-07'和'2011-05-08'之間的價格? – Jakub 2011-05-05 13:00:56

+0

這個查詢的另一個問題是Andriy M正確地指出了什麼 - 如果您想要在未被數據覆蓋的時期內獲得價格,該怎麼辦? – Jakub 2011-05-05 13:21:22

1

不知道我完全理解的問題,但對於這一點:

select * 
from prices 
where not exists (
    select 1 from (
    select from_date - lag(to_date) over (partition by null order by from_date asc) as days_diff 
    from prices 
    where from_date >= DATE '2011-05-01' 
     and to_date < DATE '2011-07-01' 
) t 
    where coalesce(days_diff, 0) > 1 
) 
order by from_date 
0

下面就來解決它,而fonky方式:

WITH RECURSIVE t AS (
    SELECT * FROM d WHERE '2011-05-02' BETWEEN start_date AND end_date 
    UNION ALL 
    SELECT d.* FROM t JOIN d ON (d.key=t.key AND d.start_date=t.end_date+'1 DAY'::INTERVAL) 
    WHERE d.start_date <= '2011-05-09') 
    SELECT sum(price), min(start_date), max(end_date) 
    FROM t 
    HAVING min(start_date) <= '2011-05-02' AND max(end_date)>= '2011-05-09'; 
0

我認爲你需要結合窗口功能和熱膨脹係數:

WITH 
raw_rows AS (
SELECT your_table.*, 
     lag(to_date) OVER w as prev_date, 
     lead(from_date) OVER w as next_date 
FROM your_table 
WHERE ... 
WINDOW w as (ORDER by from_date, to_date) 
) 
SELECT sum(stuff) 
FROM raw_rows 
HAVING bool_and(prev_date >= from_date - interval '1 day' AND 
       next_date <= to_date + interval '1 day'); 

http://www.postgresql.org/docs/9.0/static/tutorial-window.html

http://www.postgresql.org/docs/9.0/static/queries-with.html