我正在尝试加入2个表来查找下一个交付日期之前的日期。
一张表是零件编号和补货日期
part restock_date
123 01/01/15
123 04/01/15
123 06/30/15
123 09/28/15
234 01/25/15
234 04/25/15
234 07/24/15
234 10/22/15
另一张表是部件号和分析日期
part analysis_date
123 02/12/15
123 03/29/15
123 05/13/15
123 06/27/15
234 03/23/15
234 05/07/15
234 06/21/15
234 08/05/15
我正在尝试创建一个联接,显示给定分析日期的下一个重新进货日期,以便我可以计算分析日期和下一个重新进货日期之间的差异。
part restock_date analysis_date days_to_restock
123 04/01/15 02/12/15 48
123 04/01/15 03/29/15 3
123 06/30/15 05/13/15 48
123 06/30/15 06/27/15 3
234 04/25/15 03/23/15 33
234 07/24/15 05/07/15 78
234 07/24/15 06/21/15 33
234 10/22/15 08/05/15 78
有什么建议吗?
答案 0 :(得分:1)
这假设您只关心零件的补货的情况,这就是为什么这是一个内连接。如果你想单独处理没有重新入库的那些,你需要将它作为左连接并添加适当的逻辑。
表格设置
DROP TABLE IF EXISTS tbl_restock;
CREATE TABLE tbl_restock (part TEXT, restock_date DATE);
INSERT INTO tbl_restock
VALUES
('123','01/01/15'),
('123','04/01/15'),
('123','06/30/15'),
('123','09/28/15'),
('234','01/25/15'),
('234','04/25/15'),
('234','07/24/15'),
('234','10/22/15');
DROP TABLE IF EXISTS tbl_analysis;
CREATE TABLE tbl_analysis (part TEXT, analysis_date DATE);
INSERT INTO tbl_analysis
VALUES
('123','02/12/15'),
('123','03/29/15'),
('123','05/13/15'),
('123','06/27/15'),
('234','03/23/15'),
('234','05/07/15'),
('234','06/21/15'),
('234','08/05/15');
解决方案1
WITH cte AS
(
SELECT
ta.part,
tr.restock_date,
ta.analysis_date,
EXTRACT(DAY FROM AGE(tr.restock_date,ta.analysis_date)) AS days_to_restock,
RANK() OVER (PARTITION BY ta.part, ta.analysis_date ORDER BY AGE(tr.restock_date,ta.analysis_date) ASC) AS dtr_rank
FROM
tbl_analysis ta
INNER JOIN
tbl_restock tr
ON (tr.part = ta.part)
AND (tr.restock_date >= ta.analysis_date)
)
SELECT
part,
restock_date,
analysis_date,
days_to_restock
FROM
cte
WHERE
dtr_rank = 1;
更新 - 解决方案2
以下是使用@ {GordonLinoff的答案启发的DISTINCT ON
方法的另一种解决方案:Multiple unwanted records in Group by clause in Postgress
SELECT
DISTINCT ON (ta.part, ta.analysis_date)
ta.part,
tr.restock_date,
ta.analysis_date,
(tr.restock_date - ta.analysis_date) AS days_to_restock
FROM
tbl_analysis ta
LEFT JOIN
tbl_restock tr
ON (tr.part = ta.part)
AND (tr.restock_date >= ta.analysis_date)
ORDER BY
part,
analysis_date,
restock_date;
<强>输出强>
答案 1 :(得分:1)
你可以通过横向连接来解决这个问题:
select t2.*, t1.restock_date,
(t1.restock_date - t2.analysis_date) as diff
from table2 t2 left join lateral
(select t1.*
from table1 t1
where t2.part = t1.part and t2.analysis_date <= t1.restock_date
order by t1.restock_date
limit 1
) t1;
答案 2 :(得分:0)
寻找连续观察的天真方式:
SELECT a.*, r.*
, (r.restock_date - a.analysis_date ) AS nday
FROM tbl_analysis a
LEFT JOIN tbl_restock r
ON a.part = r.part
AND r.restock_date >= a.analysis_date -- restock *after* analysys
AND NOT EXISTS ( SELECT * FROM tbl_restock nx -- ,but no observations inbetween
WHERE nx.part = a.part
AND nx.restock_date > a.analysis_date
AND nx.restock_date < r.restock_date
)
ORDER BY a.part,a.analysis_date
;