2011-04-16 75 views
13

我想选择每个用户的最近一次付款。我现在的查询选择用户的第一次付款。即如果用户已经做出两笔款项和payment.id s为10和11,查询选择付款ID是10的信息,我已经添加ORDER BY payments.id的用户,而不是11在MySQL中选择GROUP BY的最新行

SELECT users.*, payments.method, payments.id AS payment_id 
    FROM `users` 
     LEFT JOIN `payments` ON users.id = payments.user_id 
GROUP BY users.id 

,但查询似乎忽略它并仍选择第一笔付款。

所有帮助表示赞赏。 谢谢。

+0

可能重复最后)在MySQL ??](http://stackoverflow.com/questions/5495913/can-i-use-aggregation-function-last-in-mysql) – 2011-04-16 16:58:36

+0

请参阅上面的答案中的答案如何从组中获取最新的记录 – 2011-04-16 17:01:06

+0

即使使用MAX(payments.id),这也不会选择相应的值,即付款方法。如果我使用MAX(payments.id)运行查询,它将选择最近的付款ID,但是是第一种付款方式。 – Ryan 2011-04-16 17:02:22

回答

14

您想要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主键列)更好。

+0

+1旧的答案,但链接是非常有用的谢谢 – user2844810 2013-11-29 00:39:17

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个结果。想法?

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 
     ) 
+0

可能的重复请您详细说明此方法背后的原因吗? – 2013-08-09 12:56:54

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 
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秒。

0

我读了那么久以前下面的解决方案,但我不能找到链接信贷,但这里有云:

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 
的[我可以使用聚合函数(