Я давно читал следующее решение на SO, но не могу найти ссылку на кредит, но здесь идет речь:
SELECT users.*, payments.method, payments.id AS payment_id, payments2.id
FROM users
JOIN payments
ON users.id = payments.user_id
LEFT JOIN payments2
ON payments.user_id = payments2.user_id
AND payments.id < payments2.id
WHERE payments2.id IS NULL
Чтобы понять, как это работает, просто отбросьте WHERE payments2.id IS NULL
ивы увидите, что происходит, например, это может привести к следующему выводу (я не создал схему, чтобы проверить это, так что это псевдо-вывод).Предположим, что в payments
есть следующие записи:
id | user_id | method
1 | 1 | VISA
2 | 1 | VISA
3 | 1 | VISA
4 | 1 | VISA
И приведенный выше SQL (без предложения WHERE payments2.id IS NULL
) должен выдать:
users.id | payments.method | payments.id | payments2.id
1 | VISA | 1 | 2
1 | VISA | 1 | 3
1 | VISA | 1 | 4
1 | VISA | 2 | 3
1 | VISA | 2 | 4
1 | VISA | 3 | 4
1 | VISA | 4 | NULL
Как вы можете видетьпоследняя строка дает желаемый результат, и поскольку payments2.id > 4
нет, LEFT JOIN приводит к payments2.id = NULL
.
Я обнаружил, что это решение намного быстрее (из моих ранних тестов), чем принятоеответ.
Использование другой схемы, но аналогичного запроса, из 16095 записей:
select as1.*, as2.id
from allocation_status as1
left join allocation_status as2
on as1.allocation_id = as2.allocation_id
and as1.id < as2.id
where as2.id is null;
16095 rows affected, taking 4.1ms
По сравнению с принятым ответом MAX / подзапрос:
SELECT as1.*
FROM allocation_status as1
JOIN (
SELECT max(id) as id
FROM allocation_status
group by allocation_id
) as_max on as1.id = as_max.id
16095 rows affected, taking 14.8ms