подзапрос с агрегацией - PullRequest
0 голосов
/ 19 декабря 2018

Мне трудно выяснить, как получить номер проекта или название проекта из таблицы, в которой работает наибольшее количество сотрудников

create table Pro_works_on
(
    EID char(9) ,
    PNO char(9) ,
    Pro_HOURS smallint not null,
    constraint pk_Pro_works_on primary key(EID,PNO),
);

SELECT
  p.PNO
FROM
  Pro_works_on AS p
 ,(
    SELECT
      COUNT(p.EID) AS numOfEmployee
     ,p.PNO
    FROM
      Pro_works_on AS p
    GROUP BY
      p.PNO
  ) AS L
WHERE
  MAX(L.numOfEmployee) = COUNT(p.EID);

Выдает следующую ошибку:

Подзапрос возвратил более 1 значения.Это недопустимо, если подзапрос следует =,! =, <, <=,>,> = Или когда подзапрос используется в качестве выражения.

Ответы [ 5 ]

0 голосов
/ 19 декабря 2018

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

SELECT *
FROM (
    SELECT p.PNO
        , count(*) AS empCount
        , RANK() OVER (ORDER BY count(*) DESC) AS r
    FROM Pro_works_on p
    GROUP BY p.PNO
) s1
WHERE r = 1

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

0 голосов
/ 19 декабря 2018

Разбейте свою проблему на шаги.

Во-первых, вам нужно знать, сколько сотрудников назначено для каждого проекта.Таким образом, вы будете знать, у кого из них больше всего сотрудников.Чтобы сделать это, используйте COUNT с GROUP BY.

SELECT 
  p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
  Pro_works_on AS p
GROUP BY
  p.PNO

Далее, пусть ваш запрос разместит ваши результаты в нужном вам порядке, используя ORDER BY.Вы хотите, чтобы на первом месте был проект с наибольшим количеством сотрудников, поэтому поместите их в конечный порядок DESC.

SELECT 
  p.PNO, COUNT(p.EID) AS numOfEmployee
FROM
  Pro_works_on AS p
GROUP BY
  p.PNO
ORDER BY COUNT(p.EID) DESC;

Наконец, поскольку вам нужен только один проект с наибольшим количеством сотрудников, добавьте ограничитель строк,В SQL Server это делается с помощью выражения TOP (N).А поскольку вас заботит только номер проекта, а не фактическое количество сотрудников, вы можете взять COUNT из результатов и просто оставить его в ORDER BY.

SELECT TOP(1) WITH TIES
  p.PNO
FROM
  Pro_works_on AS p
GROUP BY
  p.PNO
ORDER BY COUNT(p.EID) DESC;

РЕДАКТИРОВАТЬ : Добавлено WITH TIES в зависимости от вопроса ОП в комментариях.

0 голосов
/ 19 декабря 2018

для агрегированного результата, вы должны использовать для фильтра, а не где

select L.PNO 
    from Pro_works_on p, (
    select count(p.EID) as numOfEmployee
    ,p.PNO
    from Pro_works_on p
    group by p.PNO) L
HAVING  MAX(L.numOfEmployee)=numOfEmployee

, но, возможно, вы можете использовать более простой способ избежать проблемы, связанной с группой, используя порядок и предел 1

    select L.PNO 
    (
        select count(p.EID) as numOfEmployee
        , p.PNO
        from Pro_works_on p
        group by p.PNO
    ) L 
    order by numOfEmployee DESC 
    LIMIT 1 
0 голосов
/ 19 декабря 2018

Чтобы получить проект с наибольшим количеством сотрудников, я бы сделал:

with
x as (
  select
    pno,
    count(eid) as tot_emp
  from pro_works_on
  group by pno
),
y as (
  select max(tot_emp) as max_emp from x
)
select 
  x.pno
from x
join y on y.max_emp = x.tot_emp
0 голосов
/ 19 декабря 2018

Используйте order by и какое-то ограничивающее предложение - если вы хотите одну строку.В стандартном SQL:

select p.PNO, count(*) as numOfEmployee 
from Pro_works_on p
group by p.PNO
order by count(*) desc
fetch first 1 row only;

В SQL Server вы должны использовать top (1) or top (1) с связями`:

select top (1) p.PNO, count(*) as numOfEmployee 
from Pro_works_on p
group by p.PNO
order by count(*) desc;
...