如何按日期订购多个一对一关系的两个表?

问题描述 投票:2回答:3

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

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)将无法正常工作。

sql join one-to-many
3个回答
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')

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

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
    )
© www.soinside.com 2019 - 2024. All rights reserved.