SQL Query для объединения двух таблиц на основе самой близкой отметки времени
У меня есть две таблицы в SQL, и мне нужно иметь возможность сделать соединение, основанное на отметке времени в таблице B, которая раньше или равна отметке времени в таблице A.
Итак, вот некоторые поддельные данные для двух таблиц и желаемый результат:
Закрытые случаи (таблица A)
| id | resolution | timestamp |
------------------------------------------------
| 1 | solved | 2006-10-05 11:55:44.888153 |
| 2 | closed | 2007-10-07 12:34:17.033498 |
| 3 | trashed | 2008-10-09 08:19:36.983747 |
| 4 | solved | 2010-10-13 04:28:14.348753 |
Классификация (таблица B)
| id | value | timestamp |
-------------------------------------------------
| 1 | freshman | 2006-01-01 12:02:44.888153 |
| 2 | sophomore | 2007-01-01 12:01:19.984333 |
| 3 | junior | 2008-01-01 12:02:28.746149 |
Желаемые результаты
| id | resolution | timestamp | value |
--------------------------------------------------------------
| 1 | solved | 2006-10-05 11:55:44.888153 | freshman |
| 2 | closed | 2007-10-07 12:34:17.033498 | sophomore |
| 3 | trashed | 2008-10-09 08:19:36.983747 | junior |
| 4 | solved | 2010-10-13 04:28:14.348753 | junior |
Итак, я знаю, что код должен выглядеть следующим образом: я просто не могу понять, что делать с частью ON
JOIN
($ 1 и $2 - переменные, которые будут переданы):
SELECT case.id, case.resolution, case.timestamp, class.value
FROM closed_cases AS case
LEFT JOIN classifications AS class ON ???
WHERE case.timestamp BETWEEN $1 AND $2;
Я знаю, что могу использовать суб-выбор, но это будет работать, по крайней мере, на несколько тысяч строк, возможно, больше, и мне нужно, чтобы это было очень быстро; поэтому я надеялся на простой пункт, который мог бы это сделать.
Ответы
Ответ 1
Если вы можете внести изменения в структуры таблиц, я рекомендую изменить классификационную таблицу, чтобы включить дату окончания, а также дату начала - гораздо проще будет присоединиться к таблице.
Если нет, я предлагаю следующее:
SELECT case.id, case.resolution, case.timestamp, class.value
FROM closed_cases AS case
LEFT JOIN (select c.*,
(select min(timestamp)
from classifications c1
where c1.timestamp > c.timestamp) timeend
from classifications c) AS class
ON case.timestamp >= class.timestamp and
(case.timestamp < class.timeend or class.timeend IS NULL)
WHERE case.timestamp BETWEEN $1 AND $2;
EDIT - с датой окончания классификации:
SELECT case.id, case.resolution, case.timestamp, class.value
FROM closed_cases AS case
LEFT JOIN classifications AS class
ON case.timestamp >= class.timestamp and case.timestamp < class.timeend
WHERE case.timestamp BETWEEN $1 AND $2;
Ответ 2
измените отметку времени и используйте int в качестве ключа для подключения таблиц. это будет работать намного быстрее, чем сравнение даты
таблица 1
field1
field2
field3
ConnectorField
table2
field1
field2
field3
ConnectorField
и все, что вам нужно сделать, это
выберите * из таблицы1 T1 таблица внутреннего соединения2 T2 на T1.ConnectorField = T2.ConnectorField
Ответ 3
SELECT case.id, case.resolution, case.timestamp, class.value
FROM closed_cases AS case
LEFT JOIN classifications AS class
ON case.timestamp >= class.timestamp
WHERE case.timestamp BETWEEN $1 AND $2;