根据日期将最新记录加入另一个记录

时间:2019-05-29 05:42:31

标签: sql postgresql date greatest-n-per-group

我有两个表-像这样将它们称为weekcontract

Week                                    Contract    
emp_id | starting   | data1 |  ...   emp_id | from_date  | data2 | ...
-------|------------|-------|--      -------|------------|-------|--
12     | 2019-01-08 | abcd  |        12     | 2018-08-01 | efgh  | 
12     | 2019-01-15 | abcd  |        13     | 2018-10-02 | efgh  | 
12     | 2019-01-22 | abcd  |        13     | 2019-01-15 | ijkl  | 
13     | 2019-01-08 | abcd  |        13     | 2019-03-19 | mnop  | 
13     | 2019-01-15 | abcd  |        14     | 2017-02-02 | efgh  | 
13     | 2019-01-22 | abcd  |        15     | 2018-01-19 | efgh  | 

week.starting字段是一个日期(定期设置为午夜的日期时间)。 (emp_id,开始)的特定组合是唯一的。 from_date字段也是记录contract记录适用的开始时间的日期。这可能是将来的事情,所以我们不能仅仅做MAX(from)并为每位员工获得正确的合同。当前,(emp_id,from_date)是唯一的,但我不想依赖于此。 week.startingcontract.from_date可以相同。

我想要一个查询,该查询返回整个week记录,并且对于每个记录,返回当时contract处于活动状态的记录,即from_date最大的记录而仍然小于或等于week.starting。如果我有特定的一周时间要获得这份合同,这是一个非常直接的最大的每组n问题:

SELECT * FROM contract 
WHERE contract.emp_id = @emp_id AND contract.from_date <= @starting
ORDER BY contract.from_date DESC
LIMIT 1

但是我无法确定如何将其作为查询的一部分来获取week中的每条记录。我所遇到的特殊障碍意味着尽管这是一系列常见的问题,但我仍无法找到答案。我似乎无法将week.starting传递到子查询中,并且我似乎也无法在联接中使用L​​IMIT。到目前为止,我最好的尝试是加入了少于给定一周的所有合同。

哪个查询将返回我要查找的结果?

emp_id | starting   | from_date  | data1 | data2 | ...
-------|------------|------------|-------|-------|--
12     | 2019-01-08 | 2018-08-01 | abcd  | efgh  |
12     | 2019-01-15 | 2018-08-01 | abcd  | efgh  |
12     | 2019-01-22 | 2018-08-01 | abcd  | efgh  |
13     | 2019-01-08 | 2018-10-02 | abcd  | efgh  |
13     | 2019-01-15 | 2019-01-15 | abcd  | ijkl  |
13     | 2019-01-22 | 2019-01-15 | abcd  | ijkl  |

2 个答案:

答案 0 :(得分:1)

您应该能够使用窗口功能在过滤将来的合同并分配等级之后及时订购合同。然后,您可以选择排名最高的最新消息。

尚未对此进行测试,但应类似于:

select * from (
    select w.*, c.from_date, c.data2,
        row_number() over (partition by c.emp_id, w.starting order by c.from_date desc) as latest
    from week w
    join contract c on c.emp_id = w.emp_id and c.from_date <= w.starting
) as sub where latest = 1

答案 1 :(得分:1)

在Postgres中,您可以使用横向联接:

select w.*, c.*
from weeks w left join lateral
     (select c.*
      from contract c
      where c.emp_id = w.emp_id and
            c.from_date <= w.starting
      order by c.from_date desc
      fetch first 1 row only
     ) c;