Выбор нескольких строк, содержащих максимальное значение из объединения в SQL - PullRequest
0 голосов
/ 31 октября 2018

Я прочитал несколько других постов о подобной проблеме здесь, но ни один из них, кажется, не отвечает на мою проблему.

У меня есть таблица works_on, которая содержит все часы из проекта, над которым работали сотрудники:

     id     pno  hours

 123456789   1   32.50
 123456789   2    7.50
 333445555   2   10.00
 333445555   3   10.00 
 333445555  10   10.00
 ...

И еще одна таблица project, в которой указано название каждого из соответствующих номеров проекта (pno) в таблице works_on:

   pname           pno  location 

 ProductX           1   Bellaire 
 ProductY           2   Sugarland
 ProductZ           3   Houston
 Computerization   10   Stafford
...

Я пытаюсь получить имя (я) проекта (ов) с наивысшими суммарными часами БЕЗ использования ограничений SELECT TOP или LIMIT, так как мы не знаем, сколько существует «максимальных» значений.

Я могу объединить часы следующим образом:

SELECT p.pname, sub.hours FROM company.project p
JOIN
    (SELECT w.pno, SUM(IFNULL(w.hours, 0)) AS hours FROM company.works_on w
     GROUP BY w.pno) AS sub
ON p.pnumber = sub.pno;

Возвращение результата:

   pname           hours      

 ProductX          52.50
 ProductY          37.50
 ProductZ          50.00
 Computerization   55.00
 Reorganization    25.00
 Newbenefits       55.00

т. Е. компьютеризация и newbenefits в идеале должны быть возвращены, так как они имеют самые высокие совокупные часы, но я не могу выполнить MAX-запрос, который дает мне этот результат.

Есть ли обходной путь для выбора максимального результата без использования ограничения TOP или SORT / LIMIT?

1 Ответ

0 голосов
/ 31 октября 2018

Это сложно сделать в MySQL без помощи аналитических функций. Вот один из способов:

SELECT p.pname, sub.hours
FROM company.project p
INNER JOIN
(
    SELECT pno, SUM(hours) AS hours
    FROM company.works_on
    GROUP BY pno
) sub
    ON p.pnumber = sub.pno
WHERE
    sub.hours = (SELECT SUM(hours) FROM company.works_on
                 GROUP BY pno ORDER BY SUM(hours) DESC LIMIT 1);

Если вы используете MySQL 8+ или более поздней версии, тогда мы можем воспользоваться RANK():

SELECT pname, hours
FROM
(
    SELECT p.pname, sub.hours,
        RANK() OVER (PARTITION BY p.pname ORDER BY sub.hours DESC) rnk
    FROM company.project p
    INNER JOIN
    (
        SELECT pno, SUM(hours) AS hours
        FROM company.works_on
        GROUP BY pno
    ) sub
) t
WHERE rnk = 1;
...