Присоединяйтесь к столам по подходящему периоду - PullRequest
0 голосов
/ 15 декабря 2011

В базе данных 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

Так что я бы хотелполучить объединенную таблицу, добавив к элементам таблицы наиболее подходящий период (если совпадает).Период будет совпадать, если дата_элемента элемента находится после даты начала периода.

Например, для «car» дата - 01/12/2011, поэтому я перехожу к периодам таблицы, и там я вижу, что все периоды начинаются после этой даты, поэтому я должен установить ее на ноль.Если я выберу «screen», то дата будет 11/12/11, поэтому в периоды я должен взять period2, потому что это последний, который соответствует.

Таким образом, объединенная таблица приведет к:

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

Каков наилучший способ сделать это объединение?

Спасибо

Ответы [ 2 ]

2 голосов
/ 16 декабря 2011
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 голосов
/ 15 декабря 2011

Перекрестное применение или сопутствующий подзапрос сработает.

Подход подзапроса, поскольку перекрестное применение применяется только для SQL Server 2005 (UnTested)

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...