MySql select语句获取每个client_id的最新行

时间:2012-07-05 10:48:44

标签: mysql database select

嗨我有一个mysql select语句的问题我无法理解,

表client_directory_data

id int, 验证了int, client_id int, 创建时间戳, 描述longtext

通过创建的desc

从client_directory_data中选择*,其中验证= 1个订单

但是这会为每个client_id选择多行

我需要做的是选择每个client_id,其中已验证= 1但只获取每个client_id的最新行,我希望这是有道理的。

3 个答案:

答案 0 :(得分:4)

这是我一直面临的问题。幸运的是,这是一个很好的小技巧:

SELECT
client_id,
SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY created DESC),",",1) AS `id`
FROM client_directory_data
WHERE verified = 1
GROUP BY client_id

如果你想要整行,你可以像这样加入它:

SELECT
*
FROM (
  SELECT
  client_id,
  SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY created DESC),",",1) AS `id`
  FROM client_directory_data
  WHERE verified = 1
  GROUP BY client_id
) ids
JOIN client_directory_data USING (id);

当然,如果您无论如何都要通过索引字段进行排序(因此您可以有效地加入),最好使用MAX(id) AS id,尽管它实际上对性能影响很小。使用MAX()的主要原因是为了使代码更简单一些。它还避免了如果字段包含逗号(您可以使用其他分隔符进行组连接)或达到最大GROUP_CONCAT长度(可以使用SET group_concat_max_len = xxx;进行扩展并且仅导致警告)时可能遇到的陷阱)。

我可以看到为什么这会直观地看起来会出现性能问题,但它实际上是我为这些查询找到的最好的执行方法 - 尤其是在大型表格上。

以下是我从目前可用的一些较大的表中获取的一些基准测试,比较了该线程中的三种方法。

查询A :(约5,000条记录,~900条结果,非索引字段)

  • GROUP_CONCAT方法:0.0100秒
  • MAX方法:0.102秒
  • LEFT JOIN方法:0.0082秒

查询B :(约300,000条记录,约95,000条结果)

  • GROUP_CONCAT方法:1.8618秒
  • MAX方法:1.7904秒
  • LEFT JOIN方法:6.4649秒

查询C :(约300,000条记录,~7条结果)

  • GROUP_CONCAT方法:0.103秒
  • MAX方法:0.0102秒
  • LEFT JOIN方法:( 4小时后我感到无聊)

查询D :(约500,000条记录,〜5,000个不同的被分组字段值)

  • GROUP方法:0.1355秒
  • MAX方法:0.0429秒
  • LEFT JOIN方法:( 10分钟后我感到无聊)

答案 1 :(得分:3)

这是有道理的,也是一个经典的问题。

假设the most recent row is the one with highest id,您可以使用:

SELECT *
FROM client_directory_data c
LEFT JOIN client_directory_data d ON c.client_id = d.client_id AND d.verified = 1 AND d.id > c.id
WHERE d.id IS NULL
    AND c.verified = 1;

您可以对此查询模式here进行说明。

答案 2 :(得分:0)

将id作为表client_directory_data

的主键