T-SQL GROUP BY: Melhor maneira de incluir outras colunas agrupadas
-
06-07-2019 - |
Pergunta
Eu sou um usuário do MySQL que está tentando porta algumas coisas sobre a MS SQL Server.
Estou juntando um par de mesas, e agregar algumas das colunas via GROUP BY.
Um exemplo simples seria funcionários e projetos:
select empID, fname, lname, title, dept, count(projectID)
from employees E left join projects P on E.empID = P.projLeader
group by empID
... que iria trabalhar no MySQL, mas MS SQL é mais rigorosa e exige que tudo é ou fechado em uma função de agregação ou faz parte da cláusula GROUP BY.
Então, é claro, neste exemplo simples, eu suponho que eu poderia incluir apenas as colunas extras no grupo pela cláusula. Mas a consulta real que eu estou lidando com é muito complicado, e inclui um conjunto de operações realizadas em algumas das colunas não agregados ... ou seja, ele iria ficar muito feio para tentar incluir todos eles no grupo por cláusula .
Assim, há uma maneira melhor de fazer isso?
Solução
Você pode obtê-lo para trabalhar com algo em torno dessas linhas:
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
Desta forma, você evitar o extra grupo por operações, e você pode obter todos os dados que você deseja. Além disso você tem uma melhor chance de fazer bom uso de índices em alguns cenários (se você não está voltando a informação completa), e pode ser melhor combinado com paginação.
Outras dicas
"ele iria ficar muito feio para tentar incluir todos eles no grupo por cláusula."
Sim - que é a única maneira de fazê-lo * - basta copiar e colar as colunas não agregados no grupo pela cláusula, remova os aliases e que é tão bom quanto ele ganha ...
* você poderia envolvê-la em um SELECT aninhada mas isso é provavelmente tão feio ...
MySQL é incomum - e tecnicamente não compatível com o padrão SQL - em que lhe permite omitir os itens da cláusula GROUP BY. No SQL standard, cada coluna não-agregada na lista SELECT deve ser listados na íntegra na cláusula GROUP BY (por nome ou por número de ordem, mas que é obsoleto).
(Oh, embora MySQL é incomum, é bom que ele permite que a taquigrafia.)
Você não precisa participar da subconsulta, uma vez que não é necessário para fazer grupo por base em empID de funcionários - você pode fazê-lo em campo projectLeader de projetos.
Com a junção interna (como eu coloquei) você vai ter lista de funcionários que têm pelo menos um projeto. Se você quiser lista de todos os funcionários simplesmente mudá-lo para se juntar a esquerda
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
Uma subconsulta na cláusula select também pode ser adequado. Ele iria trabalhar para o exemplo dado, mas pode não para a consulta complicada real que você está lidando.
select
e.empID, fname, lname, title, dept
, (select count(*) from projects p where p.projLeader = e.empId) as projectCount
from
from employees E