postgresql加入max(date)和另一个索引

时间:2016-06-05 18:55:36

标签: sql postgresql date join

我正在尝试加入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

有什么建议吗?

3 个答案:

答案 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;

<强>输出

enter image description here

答案 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
        ;