T-SQL GROUP BY: лучший способ включить другие сгруппированные столбцы - PullRequest
11 голосов
/ 09 марта 2009

Я пользователь MySQL, который пытается перенести некоторые вещи на MS SQL Server.

Я присоединяюсь к нескольким таблицам и объединяю некоторые столбцы с помощью GROUP BY.

Простой пример - сотрудники и проекты:

select empID, fname, lname, title, dept, count(projectID)
from employees E left join projects P on E.empID = P.projLeader
group by empID

... это работало бы в MySQL, но MS SQL более строг и требует, чтобы все было либо включено в агрегатную функцию, либо являлось частью предложения GROUP BY.

Так что, конечно, в этом простом примере я предполагаю, что мог бы просто включить дополнительные столбцы в предложение group by. Но фактический запрос, с которым я имею дело, довольно сложен и включает в себя кучу операций, выполняемых над некоторыми неагрегированными столбцами ... то есть, было бы ДЕЙСТВИТЕЛЬНО уродливо пытаться включить их все в предложение group by .

Так есть ли лучший способ сделать это?

Ответы [ 5 ]

16 голосов
/ 09 марта 2009

Вы можете заставить его работать с чем-то вроде этих строк:

select e.empID, fname, lname, title, dept, projectIDCount
from
(
   select empID, count(projectID) as projectIDCount
   from employees E left join projects P on E.empID = P.projLeader
   group by empID
) idList
inner join employees e on idList.empID = e.empID

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

4 голосов
/ 09 марта 2009

"Было бы ДЕЙСТВИТЕЛЬНО уродливо пытаться включить их всех в группу group by."

Да, это единственный способ сделать это * - просто скопируйте и вставьте неагрегированные столбцы в предложение group by, удалите псевдонимы, и это так же хорошо, как и получается ...

* вы можете обернуть его во вложенный SELECT, но это, вероятно, так же уродливо ...

2 голосов
/ 09 марта 2009

MySQL необычен - и технически несовместим со стандартом SQL - позволяет вам пропускать элементы из предложения GROUP BY. В стандартном SQL каждый неагрегированный столбец в списке выбора должен быть полностью указан в предложении GROUP BY (либо по имени, либо по порядковому номеру, но это не рекомендуется).

(О, хотя MySQL необычен, приятно, что он допускает сокращение.)

1 голос
/ 01 июля 2009

Вам не нужно присоединяться к подзапросу, так как нет необходимости создавать группы на основе empID от сотрудников - вы можете сделать это в поле projectLeader из проектов.

С внутренним объединением (как я выразился) вы получите список сотрудников, у которых есть хотя бы один проект. Если вы хотите список всех сотрудников, просто измените его на левое присоединение

  select e.empID, e.fname, e.lname, e.title, e.dept, p.projectIDCount
    from employees e 
   inner join ( select projLeader, count(*) as projectIDCount
                  from projects
                 group by projLeader
              ) p on p.projLeader = e.empID
0 голосов
/ 13 августа 2009

Подзапрос в предложении select также может быть подходящим. Это сработало бы для данного примера, но не для реального сложного запроса, с которым вы имеете дело.

select
        e.empID, fname, lname, title, dept
        , (select count(*) from projects p where p.projLeader = e.empId) as projectCount
from
   from employees E
...