如何按日期对具有多对一关系的两个表进行联接?

时间:2019-02-13 21:44:59

标签: sql join one-to-many

我需要连接两个表并仅获取最新记录。这是基本形式:

table1.id | table1.region | table1.important_col1
1         | NORTH AMERICA | abc
2         | CHINA         | def
2         | NORTH AMERICA | hij

table2.id | table2.region | table2.transaction_date | table2.important_col2
1         | NORTH AMERICA | 2/13/2019               | xyz
1         | NORTH AMERICA | 1/13/2019               | zzz
1         | NORTH AMERICA | 12/13/2018              | xxx

所需结果:

1 | NORTH AMERICA | 2/13/2019 | abc | xyz

我想使用this answer,但如果我需要按降序分组然后按降序排序,则好像无法使用它。我将需要在右侧的多列中提供信息,但不希望在左侧重复行。

每个id的右侧可能有多达100条记录,但是我现在只需要一些可以使用的记录。预先感谢。

编辑:我还需要根据其他条件对右侧进行过滤,以使简单的MAX(table2.transaction_date)无法正常工作。

3 个答案:

答案 0 :(得分:1)

您可以使用内部窗口函数来过滤表,在此示例中,我使用了LAG,但是您可以使用ROW_NUMBER来过滤几条记录。使用滑动窗口不会更改记录数或不计为SQL聚合,即您使用where而不是having进行过滤。

SELECT 
     t1.id
    ,t2.transaction_date
    ,t1.region 
    ,t1.col1
    ,t2.important_col2
FROM table1 AS t1
OUTER APPLY (
    SELECT 
         id
        ,transaction_date
        ,LAG(transaction_date,1) over  (partition by id order by transaction_date desc) as prev_td
        ,important_col2
        FROM table2
        -- WHERE filter_by_col=1  -- additonal "right side" filtering
) as t2
where t1.id = t2.id
and t2.prev_td is null

输出:

1   2019-02-13 00:00:00.000 NORTH AMERICA   abc xyz

我用它来测试以上查询:

create table table1
    (id int,
    region varchar(30),
    col1 varchar(100));

insert into table1
values (1 ,'NORTH AMERICA' ,'abc'),
(2,'CHINA','def'),
(2,'NORTH AMERICA','hij');

create table table2
    (id int,
    region varchar(30),
    transaction_date datetime,
    important_col2 varchar(100))

insert into table2
values
    (1 ,'NORTH AMERICA',convert(datetime, '02/13/19', 1),'xyz'),
    (1 ,'NORTH AMERICA',convert(datetime, '01/13/19',1),'zzz'),
    (1 ,'NORTH AMERICA',convert(datetime, '12/13/18',1),'xxx')

答案 1 :(得分:0)

以这种方式尝试:

select table11.id, table1.region, max(table2.transaction_date) transaction_date
from table1
inner join table2
  on table1.id = table2.id
group by table1.id, table1.region

答案 2 :(得分:0)

如果您还希望在table2(交易日期除外)中显示更多列,那么仅靠汇总不能解决您的问题。

在MySQL 8.0中,您可以使用窗口函数ROW_NUMBER()来标识最新的事务记录,如下所示:

SELECT x.*
FROM (
    SELECT 
        t1.*,
        t2.*, 
        ROW_NUMBER() OVER(PARTITION BY t2.region ORDER BY t2.transaction_date DESC) rn
    FROM table1 t1
    INNER JOIN table2 t2 ON t1.region = t2.region
) x
WHERE x.rn = 1

在早期版本的MySQL中,一种解决方案是添加带有相关子查询的NOT EXISTS,以确保我们与当前区域的最新事务一起加入:

SELECT t1.*, t2.*
FROM table1 t1
INNER JOIN table2 t2
    ON t1.region = t2.region
    AND NOT EXISTS (
        SELECT 1
        FROM table2
        WHERE region = t2.region AND transaction_date > t2.transaction_date
    )