Задача «найновіший рядок у кожній групі» - класика співбесід. Кілька способів:
1. Віконна функція - працює і в PostgreSQL, і в MySQL 8+:
SELECT *
FROM (
SELECT o.*, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS rn
FROM orders o
) ranked
WHERE rn = 1;
2. DISTINCT ON - коротко, але лише PostgreSQL:
SELECT DISTINCT ON (user_id) *
FROM orders
ORDER BY user_id, created_at DESC;
3. LATERAL (PostgreSQL, MySQL 8.0.14+) - зручно, коли потрібні кілька останніх, а не одне:
SELECT u.id, last.*
FROM users u
CROSS JOIN LATERAL (
SELECT * FROM orders o WHERE o.user_id = u.id ORDER BY created_at DESC LIMIT 3
) last;
Чого уникати: GROUP BY user_id разом із MAX(created_at) і рештою колонок у SELECT - MySQL у старому режимі поверне колонки з довільного рядка групи, а не з останнього.
Для швидкодії потрібен індекс (user_id, created_at DESC): з ним LATERAL бере кілька рядків з індексу, не сортуючи всю таблицю. У Laravel цю задачу розв'язує зв'язок latestOfMany().