我正在尝试使用最近的付款选择每个用户。我现在的查询选择了用户的第一笔付款。即如果用户已进行了两次付款且payment.id
为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
我添加了ORDER BY payments.id
,但查询似乎忽略了它,仍然会选择第一笔付款。
所有帮助表示赞赏。 感谢。
答案 0 :(得分:19)
你想要groupwise maximum;本质上,将支付表分组以识别最大记录,然后将结果与自身连接起来以获取其他列:
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
主键列。
答案 1 :(得分:2)
我刚刚处理了几乎完全相同的问题,并发现这些答案很有帮助。我的测试似乎暗示你可以使它比接受的答案稍微简单,即:
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);
我没有对性能进行性能测试,但我正在处理的数据库有超过50,000个用户和超过60,000个付款,查询运行时间为0.024秒。
答案 2 :(得分:2)
我很久以前在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
答案 3 :(得分:1)
我的解决方案:
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
答案 4 :(得分:0)
更进一步,我们也可以使用:
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个结果。想法?
答案 5 :(得分:0)
我之前遇到过这种情况。分组依赖于聚合表达式或相同记录。我的研究发现最好这样做:
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
)