2011-12-15 55 views
0

連接表PostgreSQL數據庫中我有2個表像這樣的:通過適當的時期

表項目:

item_id item  save_date (date dd/mm/yy) 
---------------------------------------------- 
1   car  01/12/11 
2   wheel  10/12/11 
3   screen 11/12/11 
4   table  15/12/11 

表時間:

period_id period_name start (date dd/mm/yy) 
------------------------------------------------ 
1   period1  05/12/11 
2   period2  09/12/11 
3   period3  12/12/11 

所以我想獲得一個連接表格添加到表格項目中最適合的時期(如果在匹配上)。如果項目的save_date在該期間的開始日期之後,則期間將匹配。

例如,對於「汽車」的日期爲01/12/2011,所以我去了臺期間在那裏我可以看到各個時期在該日期之後開始,所以我必須將其設置爲null。如果我拿「屏」的日期是11/12/11所以我應該採取間隔2期間,因爲它是相匹配的最新產品。

所以連接表將導致:

item_id item  save_date period_name 
---------------------------------------------- 
1   car  01/12/11  null 
2   wheel  10/12/11  period2 
3   screen 11/12/11  period2 
4   table  15/12/11  period3 

什麼是做這個連接的最佳方式?

謝謝

+0

Period3應該是仍然有效(直到永恆),因爲沒有晚期的日期存在? – wildplasser 2011-12-15 22:43:23

回答

2
SET search_path='tmp'; 

DROP TABLE items CASCADE; 
CREATE TABLE items 
    (item_id INTEGER NOT NULL PRIMARY KEY 
    , item VARCHAR 
    , save_date date NOT NULL 
    ); 
INSERT INTO items(item_id,item,save_date) VALUES 
(1, 'car', '2011-12-01') 
,(2, 'wheel', '2011-12-10') 
,(3, 'screen', '2011-12-11') 
,(4, 'table', '2011-12-15') 
    ; 

DROP TABLE periods CASCADE; 
CREATE TABLE periods 
    (period_id INTEGER NOT NULL PRIMARY KEY 
    , period_name VARCHAR 
    , start_date date NOT NULL 
    ); 
INSERT INTO periods(period_id,period_name,start_date) VALUES 
(1, 'period1', '2011-12-05') 
,(2, 'period2', '2011-12-09') 
,(3, 'period3', '2011-12-12') 
    ; 
-- self-join to find the next interval 
WITH pe AS (
    SELECT p0.period_id,p0.period_name,p0.start_date 
     , p1.start_date AS end_date 
    FROM periods p0 
    -- must be a left join; because the most recent interval is still open 
    -- (has no successor) 
    LEFT JOIN periods p1 ON p1.start_date > p0.start_date 
    WHERE NOT EXISTS (
     SELECT * FROM periods px 
     WHERE px.start_date > p0.start_date 
     AND px.start_date < p1.start_date 
     ) 
    ) 
SELECT it.item_id 
    , it.item 
    , it.save_date 
    , pe.period_id 
    , pe.period_name 
    , pe.start_date 
    , pe.end_date 
FROM items it 
LEFT JOIN pe 
     ON it.save_date >= pe.start_date 
     AND (it.save_date < pe.end_date OR pe.end_date IS NULL) 
    ; 

結果:

item_id | item | save_date | period_id | period_name | start_date | end_date 
---------+--------+------------+-----------+-------------+------------+------------ 
     1 | car | 2011-12-01 |   |    |   | 
     2 | wheel | 2011-12-10 |   2 | period2  | 2011-12-09 | 2011-12-12 
     3 | screen | 2011-12-11 |   2 | period2  | 2011-12-09 | 2011-12-12 
     4 | table | 2011-12-15 |   3 | period3  | 2011-12-12 | 
(4 rows) 
2

交叉應用或共同相關的子查詢將工作。

子查詢方法爲跨應用僅適用於SQL Server 2005的(未經測試)

SELECT Item_Id, 
     Item, 
     Save_Date, 
     (
     SELECT MAX(Period_Name) 
      FROM Periods 
     WHERE Start = (
       SELECT MAX(start) MaxStart 
        FROM periods P 
       WHERE I.Save_Date > P.start) 
     ) AS Period_Name 
FROM ITEMS I