MySQL从包含多笔付款用户列表的表中选择最新付款

时间:2013-06-04 14:11:08

标签: mysql sql

我有一张满是用户付款的表格。每个用户都可以有多笔付款。我想为每个用户选择最新的付款方式。

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_idp.amount等其他付款字段必须对应于用户上次付款的同一行,但必须与之前的付款相对应。

如何确保当我选择MAX(p.date)时,它还会选择同一行中的其他字段。

感谢帮助。

4 个答案:

答案 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;