SQL находит среднее количество кортежей (ни max, ни min) - PullRequest
1 голос
/ 29 сентября 2019

Предположим, у меня есть две таблицы PEOPLE и WORK.Я хотел бы найти все work без максимального или минимального числа people.

ПРИМЕР:

PEOPLE

ID NAME   WORK
1  Mark   Programmer
2  Sonia  Singer
3  Jack   Programmer
4  Mirco  Welder
5  Jeff   Welder
6  Tom    Welder

WORK

ID  WORK
1   Programmer
2   Singer
3   Welder

Результат должен быть:

Programmer

Как я могу написать MySQL query как этот ??Чем вы обязательно найдете маленький набор из 3 элементов:

1 Maximum represented by Welder job done by Mirco, Jeff and Tom
2 Medium represented by Programmer done by Mark and Jack who is the Job I would like to find
3 Minimum represented by Singer done only from Sonia

Спасибо

Ответы [ 4 ]

1 голос
/ 29 сентября 2019

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

declare @people table (id int, name varchar(20), work varchar(50))
insert into @people
values (1,  'Mark'  , 'Programmer'),
(2,  'Sonia'  ,'Singer'),
(3,  'Jack',   'Programmer'),
(4,  'Mirco',  'Welder'),
(5,  'Jeff',   'Welder'),
(6,  'Tom',    'Welder')

select a.work
from ( -- A subquery that returns the count of each work
   select work, count(*) cnt
   from @people
   group by work
) a
left outer join ( -- a subquery that returns the min and max counts
   select min(cnt) mincount, max(cnt) maxcount
   from (
      select count(*) cnt
      from @people
      group by work
   ) b
) c
   on a.cnt = c.mincount
   or a.cnt = c.maxcount
where c.mincount is null
0 голосов
/ 29 сентября 2019

Если вы хотите сделать это без оконных функций:

select w.*
from work w
where w.work not in (select p.work
                     from people p
                     group by p.work
                     order by count(*) asc
                     fetch first 1 row only
                    ) and
      w.work not in (select p.work
                     from people p
                     group by p.work
                     order by count(*) desc
                     fetch first 1 row only
                    );

Обратите внимание, что в случае дубликатов учитывается только одна строка как минимум / максимум, поэтому связи могут быть возвращены.

0 голосов
/ 29 сентября 2019

Вот подход, использующий оконные функции:

  • сначала используйте агрегированный запрос для вычисления количества людей для каждой работы
  • , а затем ранжируйте работы по возрастанию и убыванию людейcount
  • наконец, отфильтруйте верхнюю и нижнюю записи

Запрос:

SELECT work
FROM (
    SELECT 
        work,
        ROW_NUMBER() OVER(ORDER BY cnt) rn_asc,
        ROW_NUMBER() OVER(ORDER BY cnt DESC) rn_desc
    FROM (
        SELECT work, COUNT(*) cnt FROM people GROUP BY work
    ) x
) x WHERE rn_asc != 1 AND rn_desc != 1

Демонстрация на DB Fiddle :

| work       |
| ---------- |
| Programmer |

Примечание. Что касается проблем, вам не нужно запрашивать таблицу work, чтобы получить ожидаемые результаты, поскольку вся соответствующая информация доступна в people.

0 голосов
/ 29 сентября 2019

Этот запрос будет работать для разновидностей SQL, которые поддерживают CTE (например, SQL Server, PostgreSQL, MySQL 8 +):

WITH counts AS
(SELECT WORK, COUNT(*) AS num
 FROM people
 GROUP BY WORK),
minmax AS 
(SELECT MIN(num) AS min, MAX(num) AS max
 FROM counts)
SELECT WORK
FROM counts c
JOIN minmax m ON c.num != m.min AND c.num != m.max

Вывод:

WORK
Programmer

Демонстрацияна dbfiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...