我有一张满是用户付款的表格。每个用户都可以有多笔付款。我想为每个用户选择最新的付款方式。
SELECT DATE_FORMAT(FROM_UNIXTIME(MAX(p.date)), "%D %M %Y") as last_payment, p.user_id, p.amount, p.period, p.txn_id, u.name
FROM payments as p
INNER JOIN users as u
ON u.id = p.user_id
GROUP BY p.user_id
ORDER BY p.date DESC
现在这似乎工作正常,last_payment
字段确实是用户最新付款的日期,唯一的问题是p.txn_id
和p.amount
等其他付款字段必须对应于用户上次付款的同一行,但必须与之前的付款相对应。
如何确保当我选择MAX(p.date)
时,它还会选择同一行中的其他字段。
感谢帮助。
答案 0 :(得分:1)
您正在寻找groupwise maximum;最常见的方法是将付款表连接回分组结果:
SELECT DATE_FORMAT(FROM_UNIXTIME(p.date), '%D %M %Y') AS last_payment,
p.user_id, p.amount, p.period, p.txn_id, u.name
FROM payments AS p NATURAL JOIN (
SELECT user_id, MAX(date) date
FROM payments
GROUP BY user_id
) t JOIN users AS u ON u.id = p.user_id
ORDER BY p.date DESC
请注意,原始查询完全有效(并且没有抛出错误)的唯一原因是MySQL's non-standard extensions to GROUP BY
:
MySQL扩展了
GROUP BY
的使用,以便选择列表可以引用未在GROUP BY
子句中命名的非聚合列。这意味着前面的查询在MySQL中是合法的。您可以通过避免不必要的列排序和分组来使用此功能来获得更好的性能。但是,当GROUP BY
中未在{{1}}中命名的每个非聚合列中的所有值对于每个组都相同时,这非常有用。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选的值是不确定的。
答案 1 :(得分:0)
尝试这样的事情
SELECT DATE_FORMAT(FROM_UNIXTIME(p.date), "%D %M %Y") as last_payment
, p.user_id, p.amount, p.period, p.txn_id, u.name
FROM payments p, users u
WHERE u.id = p.user_id
and exists (SELECT max(p1.date) from payments p1
where p1.user_id = p.user_id
having max(p1.date)=p.date
group by p.user_id, p1.date )
ORDER BY p.date DESC
答案 2 :(得分:0)
SELECT DATE_FORMAT(p.date, "%D %M %Y") as last_payment, p.user_id, p.amount, p.period, p.txn_id, u.name
FROM payments as p where
INNER JOIN users as u
ON u.id = p.user_id
GROUP BY p.user_id having FROM_UNIXTIME(p.date)=FROM_UNIXTIME(MAX(p.date))
ORDER BY p.date DESC
答案 3 :(得分:0)
SELECT u.*
, x.*
FROM payments x
JOIN (SELECT user_id,MAX(date) max_date FROM payments GROUP BY user_id) y
ON y.user_id = x.user_id
AND x.date = y.max_date
JOIN users u
ON u.id = x.user_id;