Question

Je suis un utilisateur de MySQL qui tente de transférer certaines choses sur MS SQL Server.

Je joins quelques tables et agrège certaines des colonnes via GROUP BY.

Un exemple simple serait les employés et les projets:

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

... cela fonctionnerait dans MySQL, mais MS SQL est plus strict et exige que tout soit inclus dans une fonction d'agrégat ou fasse partie de la clause GROUP BY.

Donc, bien sûr, dans cet exemple simple, je suppose que je pourrais simplement inclure les colonnes supplémentaires dans la clause group by. Mais la requête à laquelle je fais face est assez compliquée et comprend un ensemble d'opérations effectuées sur certaines des colonnes non agrégées ... c'est-à-dire qu'il serait vraiment laid d'essayer de toutes les inclure dans la clause group by. .

Alors, y a-t-il une meilleure façon de faire cela?

Était-ce utile?

La solution

Vous pouvez le faire fonctionner avec quelque chose autour de ces lignes:

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

De cette façon, vous évitez le groupe supplémentaire d'opérations et vous pouvez obtenir toutes les données que vous souhaitez. En outre, vous avez une meilleure chance de faire bon usage des index dans certains scénarios (si vous ne renvoyez pas les informations complètes), et vous pouvez mieux le combiner avec la pagination.

Autres conseils

"Cela deviendrait VRAIMENT laid d'essayer de tous les inclure dans la clause group by."

Ouais - c’est la seule façon de le faire * - il suffit de copier et coller les colonnes non agrégées dans la clause group by, de supprimer les alias et c’est aussi bon que cela devient ...

* vous pourriez l'envelopper dans un SELECT imbriqué mais c'est probablement aussi moche ...

MySQL est inhabituel - et techniquement non conforme au standard SQL - il vous permet d’omettre des éléments de la clause GROUP BY. En SQL standard, chaque colonne non agrégée de la liste de sélection doit être répertoriée dans sa totalité dans la clause GROUP BY (par nom ou par nombre ordinal, mais il est obsolète).

(Oh, bien que MySQL soit inhabituel, c’est bien qu’il permette le raccourci.)

Vous n'avez pas besoin de rejoindre la sous-requête car il n'est pas nécessaire de créer un groupe en fonction de l'empID des employés. Vous pouvez le faire sur le champ projectLeader des projets.

Avec la jointure interne (comme je le disais), vous obtenez la liste des employés ayant au moins un projet. Si vous souhaitez afficher la liste de tous les employés, il suffit de la changer pour rejoindre à gauche

  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

Une sous-requête dans la clause select pourrait également convenir. Cela fonctionnerait pour l'exemple donné mais ne le ferait peut-être pas pour la requête complexe que vous avez à traiter.

select
        e.empID, fname, lname, title, dept
        , (select count(*) from projects p where p.projLeader = e.empId) as projectCount
from
   from employees E
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top