#mysql
#mysql
Вопрос:
у меня есть такие данные.
Таблица customer
| customerId | fullName | sex
| 1 | Budi Arsana | Male
| 2 | Peter Parker | Male
и другое имя таблицы transaction
| Id | bookingDate | customer
| 1 | 2011-09-01 | 1
| 2 | 2011-09-30 | 1
| 3 | 2011-09-01 | 2
И я хочу получить результат с объединением этих 2 таблиц, которые выбирают клиента, у которого есть транзакция, а затем получают только 1 транзакцию с последней датой. Вот так
| customerId | fullName | sex | transId | bookingDate
| 1 | Budi Arsana | Male | 2 | 2011-09-30
| 2 | Peter Parker | Male | 3 | 2011-09-01
Ответ №1:
SELECT c.customerId, c.fullName, c.sex, t.Id AS transId, t.bookingDate
FROM customer c
INNER JOIN (SELECT customer, MAX(bookingDate) AS MaxDate
FROM transaction
GROUP BY customer) q
ON c.customerId = q.customer
INNER JOIN transaction t
ON q.customer = t.customer
AND q.MaxDate = t.bookingDate;
Комментарии:
1. могу ли я узнать, что означает 2-я строка?
FROM customer c
, Вы имели в видуFROM customer AS c
?2. @GusDeCooL
AS
Необязательный, поэтому обе версии означают одно и то же.3. Да, это короткая форма,
AS
можно опустить. Я бы не рекомендовал это, по крайней мере, когда он используется для псевдонимов столбцов. Легко пропустить ввод запятой, но не так легко обнаружить, что вы пропустили ее при отладке. Т.е.SELECT id group, name FROM users
может быть сложно найти. Для ввода иAS
требуется всего несколько нажатий клавиш, но ИМХО это намного облегчает чтение4. @Nikoloff Как вы можете видеть в моем ответе, я придерживаюсь смешанного подхода. Я использую столбцы
AS
псевдонимов when по указанным вами причинам, но обычно опускаю их после имен таблиц, поскольку в этом случае связь более очевидна.5. @Joe Stefanelli, согласен, поэтому я уточнил, что я говорю о столбцах, а не о таблицах 🙂
Ответ №2:
Использование объединения с самоисключением:
SELECT c.customerId, c.fullName, c.sex, t.Id AS transId, t.bookingDate
FROM customer c
LEFT JOIN transaction t ON t.customer = c.customerId
LEFT JOIN transaction t2 ON t2.customer = t.customer
AND t2.bookingDate > t.bookingDate
WHERE t2.Id IS NULL;
Принцип заключается в том, что вы создаете другое соединение с рабочей копией transaction
таблицы ( t2
) и используете его для удаления из конечного результирующего набора всех, кроме самой последней записи в transaction
( t
) .
Предостережение: это не сработает, если у вас несколько заказов в день на одного клиента. В этом случае вы можете захотеть перейти с даты на временную метку.
Комментарии:
1. 1 прекрасно работает, если вы удалите лишнее
t
transaction t t2
в своем второмLEFT JOIN
: sqlize.com/MpaCjlZb672. Ах да, спасибо @mella. Отредактировано. И спасибо за совет о sqlize. Раньше такого не видел.