Что-то вроде этого?
SELECT yourtable.id, rev, content
FROM yourtable
INNER JOIN (
SELECT id, max(rev) as maxrev FROM yourtable
WHERE yourtable
GROUP BY id
) AS child ON (yourtable.id = child.id) AND (yourtable.rev = maxrev)
Вы хотите групповой максимум ; по существу, группировать таблицу платежей, чтобы идентифицировать максимальные записи, а затем присоединить результат назад к себе, чтобы получить другие столбцы:
SELECT users.*, payments.method, payments.id AS payment_id
FROM payments NATURAL JOIN (
SELECT user_id, MAX(id) AS id
FROM payments
GROUP BY user_id
) t RIGHT JOIN users ON users.id = t.user_id
Обратите внимание, что MAX(id)
может быть не самым « недавний платеж ", в зависимости от вашего приложения и схемы: обычно лучше определить« самый последний »на основе TIMESTAMP
, чем на основе синтетических идентификаторов, таких как столбец первичного ключа AUTO_INCREMENT
.
Я давно читал следующее решение о 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
Мое решение:
SELECT
u.codigo,
u.nome,
max(r.latitude),
max(r.longitude),
max(r.data_criacao)
from TAB_REGISTRO_COORDENADAS r
inner join TAB_USUARIO u
on u.codigo = r.cd_usuario
group by u.codigo
Я уже сталкивался с этим раньше. Группировка больше предназначена для совокупных выражений или идентичных записей. Мои исследования показали, что лучше всего сделать что-то вроде этого:
SELECT u.*, p.method, p.id AS payment_id
FROM (
SELECT DISTINCT users.id
FROM users
) ur
JOIN payments p
ON p.id =
(
SELECT pt.id
FROM payments pt
WHERE pt.user_id = ur.id
ORDER BY
pt.id DESC
LIMIT 1
)
Я только что имел дело с почти той же проблемой и нашел эти ответы полезными. Мое тестирование, похоже, подсказывает, что вы можете сделать это немного проще, чем принятый ответ, а именно :
SELECT u.*, p.method, p.id AS payment_id
FROM `users` u, `payments` p
WHERE u.id = p.user_id
AND p.id = (SELECT MAX(p2.id) FROM payments p2
WHERE p2.user_id = u.id);
Я не тестировал тесты, но db, над которым я работаю, имеет более 50 000 пользователей и более 60 000 платежей и запрос выполняется за 0,024 секунды.
Сделав еще один шаг, мы также можем использовать:
select payment_id, cust_id, amount, payment_method
from my_table where payment_id in
(
select max(payment_id) from my_table group by cust_id
);
... но этот запрос также слишком длинный в моем контексте. Внутренний выбор курит быстро, но внешний занимает некоторое время, и только 124 результата от внутреннего. Идеи?