SQL Найти человека, который отработал больше всех смен за всё время/в этом месяце

Рейтинг: -2Ответов: 1Опубликовано: 10.06.2023

Дано: 2 таблицы с данными сотредников и расписанием их смен

введите сюда описание изображения

введите сюда описание изображения

Как видно, один сотрудник может работать как в первую смену, так и во вторую.

Требуется: найти сотрудника, который отработал больше всего смен за всё время, и за каждый месяц в отдельности.

Пробовал решить задачу через UNION, но почему-то в ответе какая-то дичь... создается впечатление, что COUNT считает не количество выборок, а суммирует ID.

SELECT 
    (SELECT CONCAT(person.NAME, ' ', person.PATRONYMIC) 
     FROM person 
     WHERE person.ID=schedule_.PERSON_1), 
COUNT(*)
FROM person, schedule_, holiday
GROUP BY 
    (SELECT CONCAT(person.NAME, ' ', person.PATRONYMIC) 
    FROM person WHERE person.ID=schedule_.PERSON_1)
UNION
SELECT 
    (SELECT CONCAT(person.NAME, ' ', person.PATRONYMIC) 
     FROM person WHERE person.ID=schedule_.PERSON_2), 
    COUNT(*)
FROM person, schedule_, holiday
GROUP BY 
    (SELECT CONCAT(person.NAME, ' ', person.PATRONYMIC) 
     FROM person WHERE person.ID=schedule_.PERSON_2)

введите сюда описание изображения

По возможности не давайте прямого ответа, намекните, как по-другому можно решить задачу.

Ответы

▲ 0Принят

Можно объединить количества во внутреннем запросе, а во внешнем запросе найти общую сумму, сгруппированную по идентификатору и использовать один подзапрос для составления имени.

Также использовать ORDER BY + LIMIT 1 для вывода одного сотрудника

select
  (select concat(name, ' ', patronymic) from person p where p.id = pid) pname,
  pid, sum(cc) tot
from (
  select person_1 pid, count(*) cc
  from schedule
  group by person_1
  union 
  select person_2 pid, count(*) cc
  from schedule
  group by person_2
) total
group by pid
order by tot desc, pid
limit 1

Аналогично можно добавить группировку по месяцам:

select
  (select concat(name, ' ', patronymic) from person p where p.id = pid) pname,
  pid, m,
  sum(cc) tot
from (
  select person_1 pid, month(sdate) m, count(*) cc
  from schedule
  group by person_1, month(sdate)
  union 
  select person_2 pid, month(sdate) m, count(*) cc
  from schedule
  group by person_2, month(sdate)
) total
group by pid, m
order by m, tot desc, pid

Онлайн демо