Вопрос SQL-запроса (возможное соединение / подзапрос?) - PullRequest
1 голос
/ 31 марта 2009

У меня есть две таблицы ( Управление и Сотрудник ).

Таблица управления отслеживает различные группы управления, которые управляли компанией X в последние несколько лет. Каждой команде управления присваивается идентификационный номер (то есть: managementnr), и у каждой команды есть генеральный директор (а именно, ceoname).

Таблица сотрудников отслеживает сотрудников, работающих в компании X (в основном только их имена и какая управленческая команда их наняла)

Вот код SQL:


CREATE TABLE EMPLOYEE(
    EMPLOYEENAME   VARCHAR2(15) NOT NULL,
    HIRETEAM NUMBER(2), 
    PRIMARY KEY (EMPLOYEENAME)
    );

CREATE TABLE MANAGEMENT(
    MANAGEMENTNR NUMBER(2) NOT NULL,
    CEONAME VARCHAR2(20) NOT NULL,
    PRIMARY KEY (MANAGEMENTNR,CEONAME)
    );  

Я пытаюсь сформировать запрос SQL, чтобы получить адрес управления, в котором было нанято наибольшее количество сотрудников. Я пытался использовать:

SELECT HIRETEAM,max(count(HIRETEAM)) 
 from EMPLOYEE 
group by HIRETEAM

но я продолжаю получать:

  ORA-00937: not a single-group group function 

(я использую Oracle)

После нескольких часов Google-фу, я наконец понял, что означает эта ошибка, однако я все еще не могу придумать какой-либо другой способ сформировать этот запрос. Я пытался использовать подзапросы / объединения, но все еще ничего. Я очень плохо знаком с SQL в целом. Если кто-нибудь может помочь, я был бы очень благодарен!

Спасибо за ваше время =]
- Эван Лестрейндж

Ответы [ 5 ]

3 голосов
/ 31 марта 2009

Я думаю, что вы ищете это:

WITH counts_hireteam as (
   SELECT HIRETEAM
        , count(*) count_hireteam
     from EMPLOYEE 
   group by HIRETEAM
   order by count(*) desc
) 
select HIRETEAM  
  from counts_hireteam
 where rownum = 1;
2 голосов
/ 31 марта 2009

«Правильный» способ сделать это на самом деле что-то вроде:

SELECT m.ceoname, COUNT(1), ROW_NUMBER() OVER (ORDER BY COUNT(1) DESC)
FROM management m
JOIN employee e ON m.managementnr = e.hireteam
GROUP BY m.ceoname

Вы попадаете в темную область запросов Top-N, и я направлю вас к этой превосходной колонке Ask Tom на Top-N . Другие ответы работают в простых случаях, но это когда вы начинаете хотеть делать такие вещи, как возвращение трех лучших команд управления (по количеству сотрудников) и делать это последовательно, чтобы столкнуться с проблемами.

Согласованность является ключевым моментом. Как отмечает Том:

Содержит ли предложение GROUP BY в запросе гарантировать, что выходные данные будут отсортировано по столбцам GROUP BY в заказ, даже если нет ORDER BY пункт

До тех пор, пока не будет ЗАКАЗАТЬ оператор по запросу, строки возвращение не может быть принято в Любой заказ. Без ЗАКАЗА, данные могут быть возвращены в любом порядке в что база данных чувствует себя как возвращая это. Это всегда было правда и всегда будет правдой.

Фактически, в Oracle Database 10g Выпуск 2, вы увидите GROUP BY возвращать данные в случайном порядке много чаще, чем раньше:

Используя этот пример данных:

INSERT INTO employee VALUES ('Bob',1);
INSERT INTO employee VALUES ('Sue',1);
INSERT INTO employee VALUES ('John',1);
INSERT INTO employee VALUES ('James',2);
INSERT INTO employee VALUES ('Mary',2);
INSERT INTO employee VALUES ('Ron', 2);
INSERT INTO employee VALUES ('Jane',3);
INSERT INTO employee VALUES ('Luke',4);
INSERT INTO employee VALUES ('Rob',4);
INSERT INTO employee VALUES ('Tim', 5);

INSERT INTO management VALUES (1, 'Kate');
INSERT INTO management VALUES (2, 'Larry');
INSERT INTO management VALUES (3, 'Jake');
INSERT INTO management VALUES (4, 'Sarah');
INSERT INTO management VALUES (5, 'Tom');
2 голосов
/ 31 марта 2009

Получить первую строку из этого запроса:

select hireteam,count(*) from EMPLOYEE group by hireteam order by count(*) desc
0 голосов
/ 31 марта 2009

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

select * from (
    select hireteam, count(hireteam) count
    from employee
    group by hireteam
    order by count(hireteam) desc, hireteam asc )
where rownum = 1

Чтобы получить все значения найма команды, у которых больше всего сотрудников (включая связи):

select * from (
    select hireteam,
           count(hireteam) count,
           rank() over (order by count(hireteam) desc) rank
    from   employee
    group by hireteam)
where rank = 1;
0 голосов
/ 31 марта 2009

Таким образом, вы получаете все команды с количеством наемных сотрудников.

select
    Management.ManagementNr,
    Management.CeoName,
    count(Employee.EmployeeName)   
from 
    Employee 
inner join 
    Management on Employee.HireTeam = Management.ManagementNr   
group by 
    Management.ManagementNr   
order by 
    count(Employee.EmployeeName) desc

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

select Employee.HireTeam   
from Employee   
group by Employee.HireTeam   
having count(EmployeeName) = select max(GroupSize)
   from select count(EmployeeName) as GroupSize
      from Employee group by Employee.HireTeam

Это может фактически вернуть несколько строк, если несколько менеджеров нанимают одинаковое количество сотрудников. И это ужасно ... но я не знаю лучшего способа сделать это в одном запросе.

...