在mysql中用groupby选择最近的行

hkmswyz6  于 2021-06-20  发布在  Mysql
关注(0)|答案(6)|浏览(294)

我正在尝试选择每个用户的最新付款。我现在的查询选择用户的第一次付款。i、 e.如果一个用户已经支付了两次,并且 payment.id s是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 ,但查询似乎忽略了它,仍然选择第一笔付款。
感谢大家的帮助。谢谢。

6rqinv9w

6rqinv9w1#

我很久以前就读过下面的解决方案,但是我找不到信贷的链接,下面是:

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 ,左连接将导致 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/subquery的接受答案相比:

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
6tqwzwtp

6tqwzwtp2#

我刚刚处理了几乎完全相同的问题,发现这些答案很有用。我的测试似乎表明你可以使它比公认的答案稍微简单一点,即:

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);

我还没有测试性能的差异,但数据库我的工作有超过50000个用户和超过60000支付和查询运行在0.024秒。

gajydyqb

gajydyqb3#

我以前见过这个。groupby更适用于聚合表达式或相同的记录。我的研究发现这样做是最佳实践:

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
        )
gstyhher

gstyhher4#

您需要groupwise最大值;本质上,对payments表进行分组以标识最大记录,然后将结果与它自身连接起来以获取其他列:

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 主键列。

3j86kqsm

3j86kqsm5#

更进一步,我们还可以使用:

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个结果来自内部。思想?

hpcdzsge

hpcdzsge6#

我的解决方案:

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

相关问题