SELECT 查询从每个组中返回 1 行

Posted

技术标签:

【中文标题】SELECT 查询从每个组中返回 1 行【英文标题】:SELECT query return 1 row from each group 【发布时间】:2012-12-31 18:10:13 【问题描述】:

这是一个产品表,有几百万条记录。

我想列出如下记录:我通常使用:

SELECT id, 
       product_name, 
       store_id 
FROM product
GROUP BY store_id 
ORDER BY id.

目前存在 SQL 性能问题。我需要 SQL 查询来输出这样的结果。

【问题讨论】:

请将表结构和解释语句的输出作为问题的一部分发布,以便我们可以看到为什么查询如此缓慢。确保在表定义中包含索引。 在“来自产品”的查询中提及您的表名 【参考方案1】:

有很多替代方法可以解决这个问题,我推荐的一种方法是加入一个子查询,该子查询分别为每个 @ 获取最新的 ID假设该列是 AUTO_INCREMENTed) 987654325@.

SELECT  a.*
FROM    tableName a
        INNER JOIN
        (
            SELECT  store_ID, MAX(ID) max_ID
            FROM    tableName
            GROUP BY store_ID
        ) b ON a.store_ID = b.store_ID AND
                a.ID = b.max_ID
SQLFiddle Demo

为了获得更好的性能,请务必在以下列上建立索引:IDstore_id

更新 1

如果您想对每条记录设置限制,请在下面使用,

SELECT ID, product_Name, store_ID
FROM   tableName a
WHERE
  (
     SELECT COUNT(*) 
     FROM   tableName b
     WHERE  b.store_ID = a.store_ID AND b.ID >= a.ID
  ) <= 2;
SQLFiddle Demo

【讨论】:

太棒了。但是我可以对 ID DESC 进行排序吗? 好的。我注意到它在执行计划中使用了文件排序。如何提高 SELECT 性能? 您在IDstore_id 上有索引吗?您可以添加此语句的结果吗? DESC tablename【参考方案2】:
SELECT store_id,id,product_name FROM table_name
WHERE id IN (SELECT MAX(id) FROM table_name GROUP BY store_id)
ORDER BY id

这应该可以工作,您可以根据您的需求通​​过 store_id 或 id 进行订购。

【讨论】:

@J-W:这与接受的答案有何不同(除了语法)?看来这两种情况的结果都是正确的。【参考方案3】:

请试试这个:

SELECT * FROM YOURTABLE B
JOIN (SELECT MAX(ID) MX FROM YOURTABLE GROUP BY STORE_ID) A
ON  A.STORE_ID = B.STORE_ID
AND B.ID = A.MX
GROUP BY B.STORE_ID
;

【讨论】:

以上是关于SELECT 查询从每个组中返回 1 行的主要内容,如果未能解决你的问题,请参考以下文章

按列从表组中获取3行数据

从不同的相关记录组中选择两列之一中包含重复值的所有行

计算列组中的列数

Oracle SQL:如何从组中查找记录

MySQL 简单查询

为啥 MySql 会出现“子查询返回超过 1 行”错误?