Rya*_*yan 19 mysql sql group-by
我正在尝试选择最近付款的每个用户.我现在的查询选择了用户的第一笔付款.即,如果用户进行了两次付款并且payment.ids为10和11,则查询选择具有付款ID 10的信息的用户,而不是11.
SELECT users.*, payments.method, payments.id AS payment_id
FROM `users`
LEFT JOIN `payments` ON users.id = payments.user_id
GROUP BY users.id
Run Code Online (Sandbox Code Playgroud)
我添加了ORDER BY payments.id,但查询似乎忽略它,仍然选择第一笔付款.
所有帮助赞赏.谢谢.
egg*_*yal 20
你想要groupwise最大值 ; 本质上,将支付表分组以识别最大记录,然后将结果与自身连接以获取其他列:
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
Run Code Online (Sandbox Code Playgroud)
请注意,这MAX(id)可能不是" 最近的付款 ",具体取决于您的应用程序和架构:通常最好确定基于合成标识符(例如主键列)的" 最新 " .TIMESTAMPAUTO_INCREMENT
我刚刚处理了几乎完全相同的问题,发现这些答案很有帮助。我的测试似乎表明您可以使其比接受的答案稍微简单一些,即:
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);
Run Code Online (Sandbox Code Playgroud)
我没有对差异进行性能测试,但我正在处理的数据库有超过 50,000 个用户和超过 60,000 笔付款,查询运行时间为 0.024 秒。
很久以前我阅读了以下解决方案,但我找不到信用链接,但这里是:
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
Run Code Online (Sandbox Code Playgroud)
要了解它是如何工作的,只需删除它WHERE payments2.id IS NULL,您就会看到发生了什么,例如它可以产生以下输出(我没有构建模式来测试它,所以它是伪输出)。假设有以下记录payments:
id | user_id | method
1 | 1 | VISA
2 | 1 | VISA
3 | 1 | VISA
4 | 1 | VISA
Run Code Online (Sandbox Code Playgroud)
上面的 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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,最后一行产生了所需的结果,由于没有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
Run Code Online (Sandbox Code Playgroud)
与 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
Run Code Online (Sandbox Code Playgroud)