2009-03-09 8 views
10

Sono un utente MySQL che sta cercando di trasferire alcune cose su MS SQL Server.T-SQL GROUP BY: Il modo migliore per includere altre colonne raggruppate

Sto unendo un paio di tabelle e aggregando alcune colonne tramite GROUP BY.

Un semplice esempio potrebbe essere dipendenti e progetti:

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

... che avrebbe funzionato in MySQL, MS SQL ma è più severo e richiede che ogni cosa o è racchiuso in una funzione di aggregazione o fa parte del Clausola GROUP BY.

Quindi, in questo semplice esempio, presumo di poter includere solo le colonne aggiuntive nella clausola group by. Ma la query vera e propria con cui ho a che fare è piuttosto complicata e include un sacco di operazioni eseguite su alcune colonne non aggregate ... cioè, sarebbe VERAMENTE brutto per cercare di includerle tutte nel gruppo in base alla clausola .

Quindi c'è un modo migliore per farlo?

+0

@ Dan, si prega di dare un'occhiata alla mia risposta, ti farà risparmiare qualche difficoltà lungo la strada ... – eglasius

risposta

15

È possibile farlo funzionare con qualcosa intorno a queste linee:

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 

In questo modo si evita il gruppo extra per operazioni, e puoi ottenere tutti i dati che desideri. Inoltre hai una migliore possibilità di fare buon uso degli indici su alcuni scenari (se non stai restituendo le informazioni complete), e può essere meglio combinato con il paging.

+0

Sì, ha dovuto aggiornare la sintassi non ho notato c'era un conteggio sul select elenco. Aggiunti anche alcune informazioni sul perché farlo in questo modo. – eglasius

4

"sarebbe VERAMENTE brutto cercare di includerli tutti nel gruppo per clausola".

Yup - questo è l'unico modo per farlo * - basta copiare e incollare le colonne non aggregati nel gruppo dalla clausola, rimuovere gli alias e questo è buono come si arriva ...

* si potrebbe avvolgetelo in un SELECT nidificato ma probabilmente è altrettanto brutto ...

2

MySQL è insolito - e tecnicamente non conforme allo standard SQL - nel consentire all'utente di omettere elementi dalla clausola GROUP BY. Nell'SQL standard, ogni colonna non aggregata nell'elenco di selezione deve essere elencata per intero nella clausola GROUP BY (per nome o per numero ordinale, ma che è deprecata).

(Oh, anche se MySQL è insolito, è bello che permette la stenografia.)

1

Non è necessario unirsi alla sottoquery in quanto non è necessario creare un gruppo basato su empID dei dipendenti: è possibile farlo sul campo projectLeader dai progetti.

Con il join interno (come ho messo) otterrete l'elenco dei dipendenti che hanno almeno un progetto. Se si desidera un elenco di tutti i dipendenti, è sufficiente modificarlo in left join

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

Una sottoquery nella clausola select potrebbe anche essere adatta. Funzionerebbe per l'esempio dato, ma potrebbe non essere adatto alla query complicata con cui si ha a che fare.

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