Супрацоўнікі з самай вялікай заробкам у аддзеле

Я знайшоў пару SQL задачы на Hacker News сёння аднак я затрымаўся на рашэнне другой задачы ў Postgres, якую я буду апісваць тут:

У вас ёсць наступная, простая структура табліцы:

enter image description here

Спіс супрацоўнікаў, якія маюць самую вялікую зарплату ў сваіх аддзелах.

Я наладзіць SQL скрыпку тут для вас гуляць. Ён павінен вярнуцца Тэры Робінсан, Лаура Уайт. Нароўні з іх імёнамі, ён павінен мець заробак і назва аддзела.

Акрамя таго, я б цікава ведаць пра запыт, які будзе вяртаць Тэры Робінсанаў (максімум зарплаты з аддзела продажаў) і Лаура Уайт (максімальная зарплата ў аддзеле маркетынгу) і пусты радок для ІТ-аддзела, з нулявы у якасці работніка; прама паказаўшы, што няма супрацоўнікаў (пры гэтым ніхто з самай высокай зарплатай) у гэтым аддзеле.

4
Ваша скрыпка была створана для MySQL, пакуль гаворка ідзе пра Postgres?
дададзена аўтар Erwin Brandstetter, крыніца
Гэта выглядае трывіяльна, ІМХО. Што вы спрабавалі?
дададзена аўтар wildplasser, крыніца

10 адказы

Вяртанне адзін Супрацоўнік з самай высокай зарплатай у аддзел.

Выкарыстоўвайце DISTINCT ON </а> для больш простага і больш хуткага запыту, які робіць усё, што вы просіце:

SELECT DISTINCT ON (d.id)
       d.id AS department_id, d.name AS department
      ,e.id AS employee_id, e.name AS employee, e.salary
FROM   departments d
LEFT   JOIN employees e ON e.department_id = d.id
ORDER  BY d.id, e.salary DESC;
->SQLfiddle (for Postgres).

Таксама зьвярніце ўвагу на левая [OUTER] JOIN які трымае аддзелы, без работнікаў у выніку.

Гэта бярэ толькі адзін супрацоўніка ў аддзел. Калі некалькі абмену самай высокай зарплаты, вы можаце дадаць больш ORDER BY пунктаў, каб выбраць адзін, у прыватнасці. У адваротным выпадку, адвольны адзін збіраецца з аднагодкаў.
Калі няма супрацоўнікаў, аддзел па-ранейшаму ў спісе, з NULL <�код /> значэння для слупкоў работніка.

Вы можаце проста дадаць слупкі, трэба ў SELECT спіс.

Find a detailed explanation, links and a benchmark for the technique in this related answer:
Select first row in each GROUP BY group?

Акрамя: Гэта анты-патэрн выкарыстаць не апісальныя імёны слупкоў, як назва або ID . Павінна быць employee_id , супрацоўнік і г.д.

Вяртанне усе супрацоўнікі з самай высокай зарплатай у аддзел.

Выкарыстоўвайце функцыю вокны ранг() (напрыклад, @Scotch ўжо размешчаны , толькі прасцей і хутчэй) :

SELECT d.name AS department, e.employee, e.salary
FROM   departments d
LEFT   JOIN (
   SELECT name AS employee, salary, department_id 
         ,rank() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk
   FROM   employees e
   ) e ON e.department_id = d.department_id AND e.rnk = 1;

Той жа вынік, як і вышэйзгаданы пытанне з вашага прыкладу (які не мае дачынення), толькі трохі павольней.

5
дададзена

This is basically what you want. Rank() Over

SELECT ename ,
       departments.name
FROM ( SELECT ename ,
              dname
       FROM ( SELECT employees.name as ename ,
                     departments.name as dname , 
                     rank() over (
                       PARTITION BY employees.department_id 
                       ORDER BY employees.salary DESC
                       )
              FROM Employees
              JOIN Departments on employees.department_id = departments.id
            ) t
       WHERE rank = 1
     ) s
RIGHT JOIN departments on s.dname = departments.name
3
дададзена
Выдае памылку ў скрыпцы.
дададзена аўтар skinkelynet, крыніца
О! Мая віна. Ці можаце вы растлумачыць, як ранг() над часткамі і працы? Магчыма, таму ён больш эфектыўны, чым прапанаваны Rachcha.
дададзена аўтар skinkelynet, крыніца
@ErwinBrandstetter Папаўся, я ніколі не выкарыстоўваў і PostgreSQL не ведаў пра Distinct On . Гэта, безумоўна, выглядае прыгажэй, чым у мяне, так што я кінуў вам костка :)
дададзена аўтар Scotch, крыніца
Вы, верагодна, ён усталяваны ў MySQL, дзе няма месца() над функцыяй. Ён сказаў Postgres.
дададзена аўтар Scotch, крыніца
Няма Probs. На першы погляд, гэта не здаецца, што іншая прапанова мае назвы аддзелаў ў запыце. Акрамя таго, мая прапанова, верагодна, мае больш высокую прадукцыйнасць, таму што іншы робіць агрэгацыю табліцы, і поўнае сканаванне, а затым зноў параўноўвае з IN п. У той час як адзін я прадставіў толькі робім подзапросов і пару маленькімі далучаецца.
дададзена аўтар Scotch, крыніца
Стыль кропкі, хоць.
дададзена аўтар Scotch, крыніца
Гэта <�я> гэта </я> прапанаваць альтэрнатыўнае рашэнне, каб выцягнуць некалькі пэраў дзяліць самую высокую зарплату за кватэру. Няясна, што ОП хоча дакладна. Але я не зусім задаволены. Я дадаў больш простую версію, каб мой адказ.
дададзена аўтар Erwin Brandstetter, крыніца
Гэта значна складаней, чым гэта павінна быць у Postgres.
дададзена аўтар Erwin Brandstetter, крыніца

Пра гэта са спасылкай на вашу скрыпку:

SELECT * -- or whatever is your columns list.
  FROM employees e JOIN departments d ON e.Department_ID = d.id
 WHERE (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
                                         FROM employees
                                     GROUP BY Department_ID)

<�Моцны> EDIT:

Як ужо адзначалася ў каментары ніжэй, калі вы хочаце ўбачыць у ІТ-аддзел таксама, з усімі NULL для запісаў супрацоўнікаў, вы можаце выкарыстоўваць RIGHT JOIN і паставіць ўмова фільтра у самым якая далучыцца пункта наступным чынам:

SELECT e.name, e.salary, d.name -- or whatever is your columns list.
  FROM employees e RIGHT JOIN departments d ON e.Department_ID = d.id
   AND (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
                                         FROM employees
                                     GROUP BY Department_ID)
2
дададзена
Ці ёсць што-небудзь для ІТ-аддзела не вяртаюцца, хоць.
дададзена аўтар skinkelynet, крыніца
Так, я ведаю. :-) Мне было б цікава ведаць (як паказана ў пытанні) як бы вярнуць радок, якая абвяшчае, што для ІТ-аддзела, то ёсць супрацоўнік нулявым і таму зарплата.
дададзена аўтар skinkelynet, крыніца
Дзякуй! Я рэдагаваў арыгінальны пытанне, каб зрабіць яго больш відавочным, я спадзяюся, што гэта лепш.
дададзена аўтар skinkelynet, крыніца
Дзякуй, я буду чакаць адказу пашыранага Scotch перад прыняццем адказу.
дададзена аўтар skinkelynet, крыніца
Гэта таму, што няма ні аднаго запісу супрацоўніка аддзела ІТ! Змесціце запіс супрацоўніка ў ІТ-аддзеле, і вы ўбачыце, што ён працуе.
дададзена аўтар Rachcha, крыніца
Зараз гэта добрае пытанне. Я адкажу на гэта. Калі ласка, пастаўце гэты пункт як рэдагаваць на сваё пытанне, так што кожны можа бачыць яго.
дададзена аўтар Rachcha, крыніца
Я адрэдагаваў мой адказ. Калі ласка, звярніцеся да Змяніць падзел.
дададзена аўтар Rachcha, крыніца

Вяртае адзін або некалькі людзей для кожнага аддзела з самай высокай заработнай платай:

SELECT result.Name Department, Employee2.Name Employee, result.salary Salary 
FROM ( SELECT dept.name, dept.department_id, max(Employee1.salary) salary 
       FROM Departments dept 
       JOIN Employees Employee1 ON Employee1.department_id = dept.department_id 
       GROUP BY dept.name, dept.department_id ) result 
JOIN Employees Employee2 ON Employee2.department_id = result.department_id 
WHERE Employee2.salary = result.salary
1
дададзена

Вазьміце паглядзіце на гэта рашэнне     ВЫБРАЦЬ       MAX (E.SALARY),       E.NAME,       D.NAME ў Дэпартаменце     Ад супрацоўнікаў E       INNER JOIN DEPARTMENTS D = О D.ID E.DEPARTMENT_ID     ГРУПА ПА D.NAME

1
дададзена
e.name верне імя ў аддзеле, а не ад імя, звязанага з максімальнай зарплатай. Гэта звязана з характарам агрэгатных функцый я баюся
дададзена аўтар Green Demon, крыніца

<�Моцны> Мяркуючы Postgres

Вяртайцеся высокай заробак з дэталямі работніка, пры ўмове, імя табліцы EMP, якія маюць супрацоўнік аддзел з dept_id

select e1.* from emp e1  inner join (select max(sal) avg_sal,dept_id from emp group by dept_id) as e2 on e1.dept_id=e2.dept_id and e1.sal=e2.avg_sal
0
дададзена

Добры стары класічны SQL:

select e1.name, e1.salary, e1.department_id
from employees e1
where e1.salary=
  (select maxsalary=max(e.salary)  --, e. department_id
     from employees e 
     where e.department_id = e1.department_id 
   group by e.department_id
   )
0
дададзена

Table1 з'яўляецца эм - EMPNO, ENAME, сал, DEPTNO

Table2 з'яўляецца аддзел - DEPTNO, DNAME.

Query could be (includes ties & runs on 11.2g):

select e1.empno, e1.ename, e1.sal, e1.deptno as department

from emp e1

where e1.sal in 

(SELECT  max(sal) from emp e, dept d where e.deptno = d.deptno group by d.dname)

 order by e1.deptno asc; 
0
дададзена
SELECT 
    e.first_name, d.department_name, e.salary 
FROM 
    employees e 
JOIN 
    departments d 
ON 
    (e.department_id = d.department_id) 
WHERE 
    e.first_name 
IN
    (SELECT TOP 2 
        first_name 
    FROM 
        employees
    WHERE 
        department_id = d.department_id);
0
дададзена
`select d.Name, e.Name, e.Salary from Employees e, Departments d,
(select DepartmentId as DeptId, max(Salary) as Salary
from Employees e
group by DepartmentId) m
where m.Salary = e.Salary
and m.DeptId = e.DepartmentId
and e.DepartmentId = d.DepartmentId`

Максімальная зарплата кожнага аддзела вылічаецца з выкарыстаннем ўнутранага запыту GROUP BY. А затым выбраць супрацоўнік, якія задавальняюць гэтыя абмежаванні.

0
дададзена