Как объединить две таблицы с идентификаторами и ближайшей следующей датой в SQL? - PullRequest
0 голосов
/ 24 октября 2019

Предположим, у меня есть две таблицы

Таблица A:

ID    Date1      Value  
A   12/12/2019  0.75
B   01/01/2020  0.2
C   02/02/2020  0.6
D   03/03/2020  0.4
E   04/04/2020  0.8
F   05/05/2020  0.9

и Таблица B:

ID2 Date2   Value2
A   18/12/2019  0.9
B   06/02/2020  0.6
C   08/03/2020  0.5
A   04/04/2020  0.8
B   06/07/2020  0.7
E   07/08/2020  0.5

Я хочу объединить их по идентификаторам, но хочу указать датычтобы выстроить линию так, чтобы запись для таблицы 1 была связана с тем же идентификатором и ближайшей будущей датой (связанной с идентификатором).

Как мне соединить их таким образом в SQL?

Я бы хотел, чтобы это выглядело примерно так:

// ID1  DATE1     VALUE1    ID2 DaTE2   VALUE 2
// A    12/12/2019  0.75    A   18/12/2019  0.9
// B    01/01/2020  0.2     B    06/02/2020 0.6
// C    02/02/2020  0.6     C   08/03/2020  0.5
// D    03/03/2020  0.4     NULL    NULL    NULL
// E    04/04/2020  0.8     E   07/08/2020  0.5
//  F   05/05/2020  0.9     NULL    NULL    NULL

Ответы [ 3 ]

0 голосов
/ 24 октября 2019

Чтобы получить дату шкафа из таблицы B для каждой записи в таблице A:

SELECT A.ID,A.`Date`, MIN(B.`Date`) AS B_Date
FROM TableA A
INNER JOIN TableB B
ON A.ID=B.ID
AND B.`Date`>A.`Date`
GROUP BY A.ID,A.`Date`


DROP TABLE IF EXISTS TableA;
DROP TABLE IF EXISTS TableB;

CREATE TABLE IF NOT EXISTS TableA (
  ID varchar(10) not null,
  `Date` date not null,
  Value decimal(5,2) not null,
  PRIMARY KEY(ID,`Date`)
);
CREATE TABLE IF NOT EXISTS TableB (
  ID varchar(10) not null,
  `Date` date not null,
  Value decimal(5,2) not null,
  PRIMARY KEY(ID,`Date`)
);

INSERT TableA(ID,`Date`,Value)
VALUES ('A', '2019-12-12', 0.75),
('B', '2020-01-01', 0.2),
('C', '2020-02-02', 0.6),
('D', '2020-03-03', 0.4),
('E', '2020-04-04', 0.8),
('F', '2020-05-05', 0.9);
INSERT TableB(ID,`Date`,Value)
VALUES ('A', '2019-12-18', 0.9),
('B', '2020-02-06', 0.6),
('C', '2020-03-08', 0.5),
('A', '2020-04-04', 0.8),
('B', '2020-07-06', 0.7),
('E', '2020-08-07', 0.5);

SELECT * FROM TableA;
SELECT * FROM TableB;

SELECT ta.*, tb.`Date` AS B_date, tb.Value as B_Value
FROM TableA ta
LEFT JOIN (
    SELECT A.ID,A.`Date`, MIN(B.`Date`) AS B_Date
    FROM TableA A
    INNER JOIN TableB B
    ON A.ID=B.ID
    AND B.`Date`>A.`Date`
    GROUP BY A.ID,A.`Date`) mb
ON ta.ID=mb.ID
AND ta.`Date`=mb.`Date`
LEFT JOIN TableB tb
ON tb.ID=mb.ID
AND tb.`Date`=mb.B_Date
ORDER BY ta.ID;
0 голосов
/ 24 октября 2019

Этого можно достичь, используя Common Table Expression, чтобы сначала агрегировать самую раннюю дату для каждого идентификатора в Таблице A, а затем выполнить простой SELECT на CTE.

;WITH CTE AS (
SELECT a.ID, min(b.Date2) AS EarliestFutureData
  FROM TableA a
  JOIN TableB b ON a.ID = b.ID2
 WHERE b.Date2 > getdate()
 GROUP
    BY a.ID
)
SELECT * FROM CTE
0 голосов
/ 24 октября 2019

Примерно так будет работать:

select *
from A inner join B on (
    A.ID1 = B.ID2 and B.Date2 = (
        select min(sub.Date2) from B sub where sub.ID2 = A.ID1 and sub.Date2 > A.Date1)
    )
)

По сути, для каждой строки в A найдите строку в B, где идентификаторы совпадают, а дата является минимальной из всех совпадающих дат вбудущее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...