MySQL:选择前 n 个最大的值?

36

我对需要返回特定列上前N行最大值的查询感到非常困惑。

例如,如果行 N-1, N, N + 1 具有相同的值。 我必须返回 仅前N行 还是 前N + 1 行。


按 ORDER BY .. LIMIT 排序,对吗?如果不是,请发布示例数据、预期输出和有效的尝试查询(但会导致不正确的结果)。 - user2864740
ORDER BY只是给我前N个吗? - Hoa Vu
ORDER BY 只是排序。LIMIT 用于设置限制。再次提供一些示例数据/结果将有很大帮助(并避免或撤回投票)。 - user2864740
谢谢,但我想问一下,我是否必须始终返回前N个值,或者如果有一些行具有相同的值(例如),我需要返回所有这些行。 - Hoa Vu
看起来你在问需求方面的问题。使用案例决定了重复项应如何处理。你想要达成什么目标? - Timo
显示剩余2条评论
3个回答

47
如果您执行以下操作:
select *
from t
order by value desc
limit N

您将获得前N行。
如果您执行以下操作:
select *
from t join
     (select min(value) as cutoff
      from (select value
            from t
            order by value
            limit N
           ) tlim
    ) tlim
    on t.value >= tlim;

或者你可以更简单地表达为:
select *
from t join
     (select value
      from t
      order by value
      limit N
    ) tlim
    on t.value = tlim.value;

以下是概念上你想要做的事情,但在 MySQL 中可能无法工作:
select *
from t
where t.value >= ANY (select value from t order by value limit N)

所以对于问题“选择前N行具有最大值”,我必须使用第一个还是第二个。因为如果我只返回前N行,可能会缺少某些行。 - Hoa Vu

7
使用以下SQL查询。
SELECT salary FROM salesperson 
ORDER BY salary DESC
LIMIT 2,1

2
你需要再多描述一点。我认为这并不是对问题的回答。 - lpratlong

1

你应该使用自连接来完成这个任务。

  1. 首先找到一个特定列中前 (n) 个可能的值
  2. 根据主键将其与同一表进行连接

例如,在下面的示例表上:

CREATE TABLE `employee` (
  `ID` INT(11)   AUTO_INCREMENT PRIMARY KEY,
  `NAME` VARCHAR(50) NOT NULL,
   `SALARY` INT(11) NOT NULL , 
    JOINING_DATE TIMESTAMP  
) ENGINE=MYISAM 

INSERT INTO  employee (NAME,salary,joining_date)    VALUES('JAMES',50000,'2010-02-02'),
('GARGI',60000,'2010-02-02'),('DAN',30000,'2010-02-02'),('JOHN',10000,'2010-02-02'),('MICHEL',70000,'2010-02-02'),
('STIEVE',50000,'2010-02-02'),('CALRK',20000,'2010-02-02'),('BINNY',50000,'2010-02-02'),('SMITH',40000,'2010-02-02'),
('ROBIN',60000,'2010-02-02'),('CRIS',80000,'2010-02-02');

有了上面的表格数据设置,查找工资最高的前三名员工的查询将是:

SELECT e1.* FROM 
(SELECT DISTINCT salary FROM Employee ORDER BY salary DESC LIMIT 3 ) S1
JOIN employee  e1 
ON e1.salary = s1.salary 
ORDER BY e1.salary DESC 

提示:-

如果您需要前四个,则只需将LIMIT 3更改为LIMIT 4


在您的示例查询中,您正在引用具有不同大小写(S1 / s1)的相同表。正如文档中所述,这是行不通的。但除此之外,答案非常好,谢谢。 - Nikl
当时我在Windows上进行了测试。感谢建议,是的,我应该在两个地方使用相同的大小写s1/S1。 - Shirishkumar Bari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接