簡體   English   中英

軌道。 使用max()選擇記錄

[英]rails. select records with max()

我有一個這樣的表,我想返回薪水最高的前兩個人(按名稱),還要返回具有相應薪水的記錄。 這是桌子

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

無論如何,有選擇記錄響應最大值嗎? 任何評論/答案深表感謝。

這個問題其實很棘手! 看起來很容易,但事實並非如此。

查詢:

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),在該函數中它返回給定名稱和id的值。為了證明給定的薪水(S(name,id))是最高的,我們必須證明我們想證明

  • ∀xS(name,id)> S(name,x)(此薪水高於該名稱的所有其他薪水)

要么

  • ¬∃xS(姓名,id)<S(姓名,x)(該姓名沒有更高的薪水)

第一種方法將需要我們獲取我不太喜歡的該名稱的所有記錄。

第二個將需要一種聰明的方式來說沒有比這個更高的記錄了。


返回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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM