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

Я пользователь 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. Но фактический запрос, с которым я имею дело, довольно сложный и включает в себя множество операций, выполняемых над некоторыми неагрегированными столбцами... т.е. Он будет ДЕЙСТВИТЕЛЬНО уродливым, чтобы попытаться включить их все в группу по пункту.

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

Ответ 1

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

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

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

Ответ 2

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

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

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

Ответ 3

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

(О, хотя MySQL необычен, приятно, что он позволяет сокращать.)

Ответ 4

Вам не нужно вступать в подзапрос, так как нет необходимости создавать группу на основе 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

Ответ 5

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

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