我有一个这样的表,我想要返回最高薪水的前两个人(按姓名),以及相应薪水的记录。这是表
id, name, salary
1, Tom, 200
2, Tom, 300
3, Bob, 400
4, Bob, 500
5, Alice, 600
6, Alice, 700
我使用了这个命令
Employer.select("employers.*, max(employers.salary) as maxsalary").group("employers.name").order("maxsalary desc").limit(2)
期望的回报:
id, name, salary
6, Alice, 700
4, Bob, 500
我得到的似乎是这样的:
id, name, salary
5, Alice, 600
3, Bob, 400
无论如何选择响应最大值的记录?任何评论/答案都非常感谢。
答案 0 :(得分:4)
这个问题实际上非常棘手! 这似乎很容易,但事实并非如此。
查询:
Employer.joins(%Q|
LEFT JOIN employers as e
ON
e.name = employers.name
AND
employers.salary < e.salary
|).where('e.salary IS NULL').order('employers.salary DESC').limit(2)
如何运作!(我去过那里)
我们希望确保每位雇主的工资最高,然后获得最高的2位。
一些理论资料(如果您只想了解查询,请跳过此部分)
让Salary成为函数S(name,id),返回给定name和id的值 为了证明给定的工资(S(姓名,身份证))是最高的,我们必须证明这一点 我们要证明
OR
第一种方法需要我们获取我不喜欢的那个名字的所有记录。
第二个需要一个明智的方式来说没有比这个更高的记录。
返回SQL
如果我们离开加入表格的名称和薪水小于联合表:
%Q|
LEFT JOIN employers as e
ON
e.name = employers.name
AND
employers.salary < e.salary
|
我们确保所有记录都有另一个具有较高薪水的记录,以便加入同一个用户:
employers.id, employers.name, employers.salary, e.id, e.name, e.salary
1 , Tom , 200 , 2 , Tom , 300
2 , Tom , 300
3 , Bob , 400 , 4 , Bob , 500
4 , Bob , 500
5 , Alice , 600 , 6 , Alice , 700
6 , Alice , 700
这将有助于我们过滤每位雇主的最高工资,而无需分组:
where('e.salary IS NULL')
employers.id, employers.name, employers.salary, e.id, e.name, e.salary
2 , Tom , 300
4 , Bob , 500
6 , Alice , 700
现在我们需要做的就是排序:
order('employers.salary DESC')
employers.id, employers.name, employers.salary, e.id, e.name, e.salary
6 , Alice , 700
4 , Bob , 500
2 , Tom , 300
然后限制
limit(2)
employers.id, employers.name, employers.salary, e.id, e.name, e.salary
6 , Alice , 700
4 , Bob , 500
这就是我们需要的答案。
我们为什么不
1
Employer.order('salary desc').limit(2)
因为这将使我们获得与姓名无关的最高工资记录
employers.id, employers.name, employers.salary
5 , Alice , 600
6 , Alice , 700
2
Employer.select('DISTINCT(name)').order('salary desc').limit(2)
问题是它只会保留名称的第一个外观然后排序
employers.id, employers.name, employers.salary
1 , Tom , 200
3 , Bob , 400
5 , Alice , 600