Соединение многих со многими осталось, где строки соединены на основе минимальной разницы дат - PullRequest
0 голосов
/ 20 ноября 2018

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

Ниже приведены некоторые образцы данных:

 /* Create and populate transactions */
    CREATE TABLE transactions (
        ssn INT,
        purchase_date DATE,
        price FLOAT
    );

    INSERT INTO transactions VALUES 
        (1111, "2018-12-31", 12.20),
        (1111, "2018-11-01", 22.23),
        (2222, "2018-08-17", 99.23),
        (4444, "2018-06-07", 13.22),
        (5555, "2018-03-05", 22.22),
        (6666, "2018-05-29", 11.11),
        (7777, "2018-10-10", 23.32),
        (8888, "2018-06-21", 44.44),
        (8888, "2018-01-19", 55.55),
        (8888, "2018-02-25", 66.53);

    /* Create and populate travel orders */
    CREATE TABLE travel_orders (
        ssn_id INT NOT NULL,
        start_date DATE
        );

    INSERT INTO travel_orders VALUES 
        (1111, "2018-12-28"),
        (1111, "2018-12-07"),
        (2222, "2018-08-12"),
        (7777, "2018-10-10"),
        (7777, "2018-10-14"),
        (8888, "2018-06-18"),
        (8888, "2018-01-19"),
        (8888, "2018-02-22");

Так, например, запись таблицы транзакций

(8888, "2018-06-21", 44.44)

присоединится к записи заказов на поездки

(8888, "2018-06-18")

и т. Д. Для остальных записей.

РЕДАКТИРОВАТЬ: ожидаемый результат что-то вроде:

+------+---------------+-------+--------+------------+
| ssn  | purchase_date | price | ssn_id | start_date |
+------+---------------+-------+--------+------------+
| 1111 | 2018-12-31    |  12.2 |   1111 | 2018-12-28 |
| 1111 | 2018-11-01    | 22.23 |   1111 | 2018-12-07 |
| 2222 | 2018-08-17    | 99.23 |   2222 | 2018-08-12 |
| 4444 | 2018-06-07    | 13.22 |   4444 | NULL       |
| 5555 | 2018-03-05    | 22.22 |   5555 | NULL       |
| 6666 | 2018-05-29    | 11.11 |   6666 | NULL       |
| 7777 | 2018-10-10    | 23.32 |   7777 | 2018-10-10 |
| 8888 | 2018-06-21    | 44.44 |   8888 | 2018-06-18 |
| 8888 | 2018-01-19    | 55.55 |   8888 | 2018-01-19 |
| 8888 | 2018-02-25    | 66.53 |   8888 | 2018-02-22 |
+------+---------------+-------+--------+------------+

У меня есть базовый стартовый код

SELECT t.*,
       o.*
FROM transactions AS t
LEFT JOIN travel_orders AS o
ON t.ssn = o.ssn_id;

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

1 Ответ

0 голосов
/ 20 ноября 2018

Этот запрос даст вам желаемые результаты. Он находит кратчайшее время между датой покупки и датой начала для каждой комбинации ssn и датой покупки (подзапросом), а затем JOIN с, чтобы в таблицах transactions и travel_orders получить требуемый результат:

SELECT t.*,
       o.*
FROM transactions t
JOIN (SELECT t.ssn, 
             t.purchase_date,
             MIN(ABS(DATEDIFF(o.start_date, t.purchase_date))) AS dd
             FROM transactions t
             LEFT JOIN travel_orders o
             ON t.ssn = o.ssn_id
             GROUP BY t.ssn, t.purchase_date) d
    ON d.ssn = t.ssn AND d.purchase_date = t.purchase_date
LEFT JOIN travel_orders o
    ON o.ssn_id = t.ssn AND ABS(DATEDIFF(o.start_date, t.purchase_date)) = d.dd
ORDER BY t.ssn, t.price

Выход:

ssn     purchase_date   price   ssn_id  start_date
1111    2018-12-31      12.2    1111    2018-12-28
1111    2018-11-01      22.23   1111    2018-12-07
2222    2018-08-17      99.23   2222    2018-08-12
4444    2018-06-07      13.22   (null)  (null)
5555    2018-03-05      22.22   (null)  (null)
6666    2018-05-29      11.11   (null)  (null)
7777    2018-10-10      23.32   7777    2018-10-10
8888    2018-06-21      44.44   8888    2018-06-18
8888    2018-01-19      55.55   8888    2018-01-19
8888    2018-02-25      66.53   8888    2018-02-22

демонстрация по SQLFiddle

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