在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位于期间的开始日期之后,则期间将匹配。
例如对于“car”,日期是01/12/2011,所以我进入表格期间,我可以看到所有期间都在该日期之后开始,所以我必须将其设置为空。如果我选择“屏幕”,那么日期是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 :(得分:2)
交叉申请或共同相关的子查询将有效。
Sub Query方法,因为Cross Apply仅适用于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
答案 1 :(得分: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)