Как можно объединить две таблицы с отношением «многие к одному», упорядоченными по дате? - PullRequest
0 голосов
/ 14 февраля 2019

Мне нужно объединить две таблицы и получить только самую последнюю запись.Вот базовая форма:

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

Я хотел использовать этот ответ , но кажется, что я не могу использовать его, еслиМне нужно сгруппировать, а затем упорядочить по убыванию даты.Мне понадобится информация в нескольких столбцах с правой стороны, но я не хочу дублировать строки с левой стороны.

В правой части может быть до 100 записей на один идентификатор, но мне просто нужно что-тоэто работает на данный момент.Заранее спасибо.

edit: мне также нужно отфильтровать правую сторону по другим критериям, чтобы простой MAX(table2.transaction_date) не работал.

Ответы [ 3 ]

0 голосов
/ 14 февраля 2019

Если в 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
    )
0 голосов
/ 14 февраля 2019

Вы можете отфильтровать свою таблицу, используя функцию внутреннего окна, я использовал 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 голосов
/ 14 февраля 2019

Попробуйте следующим образом:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...