嗨我有一个mysql select语句的问题我无法理解,
表client_directory_data
id int, 验证了int, client_id int, 创建时间戳, 描述longtext
通过创建的desc
从client_directory_data中选择*,其中验证= 1个订单但是这会为每个client_id选择多行
我需要做的是选择每个client_id,其中已验证= 1但只获取每个client_id的最新行,我希望这是有道理的。
答案 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条结果,非索引字段)
查询B :(约300,000条记录,约95,000条结果)
查询C :(约300,000条记录,~7条结果)
查询D :(约500,000条记录,〜5,000个不同的被分组字段值)
答案 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
的主键