Perché i caratteri jolly nelle istruzioni GROUP BY non funzionano?


29

Sto cercando di far funzionare la seguente istruzione SQL, ma ottengo un errore di sintassi:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

Qui, A è una tabella ampia con 40 colonne e vorrei evitare di elencare ogni nome di colonna nella clausola GROUP BY, se possibile. Ho molte di queste tabelle su cui devo eseguire una query simile, quindi dovrò scrivere una Stored Procedure. Qual è il modo migliore per affrontare questo?

Sto usando MS SQL Server 2008.

Risposte:


32

GROUP BY A.* non è consentito in SQL.

È possibile ignorare ciò utilizzando una sottoquery in cui raggruppare, quindi unire:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;

Esiste una funzionalità nello standard SQL-2003 per consentire SELECTall'elenco colonne che non sono GROUP BYnell'elenco, purché funzionalmente dipendenti da esse. Se quella funzionalità fosse stata implementata in SQL Server, la tua query avrebbe potuto essere scritta come:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A

Sfortunatamente, questa funzionalità non è stata ancora implementata, nemmeno nella versione di SQL Server 2012 - e per quanto ne so non in nessun altro DBMS. Ad eccezione di MySQL che lo ha ma in modo inadeguato (inadeguatamente come: la query sopra funzionerà ma il motore non controllerà la dipendenza funzionale e altre query scritte male mostreranno risultati sbagliati, semi-casuali).

Come @Mark Byers ci ha informato in un commento, PostgreSQL 9.1 ha aggiunto una nuova funzionalità progettata per questo scopo. È più restrittivo dell'implementazione di MySQL.


Puoi menzionare un paio di RDBMS che implementano quella parte dello standard come scritto? So, ad esempio, che MySQL ti consentirà (date le impostazioni appropriate) di includere elementi non compresi nella GROUP BYclausola SELECTnell'elenco, ma lascia indefinito su quale riga provenga quel valore (quindi se la colonna o l'espressione non è 't funzionalmente dipendente dalla espressione di raggruppamento, allora potrebbe provenire da qualsiasi riga all'interno del gruppo).
Adam Robinson,

@Adam: No, non conosco RDBMS che lo abbia implementato. MySQL ce l'ha, ma inadeguatamente, come dice il tuo commento.
ypercubeᵀᴹ

Gotcha. In realtà stavo chiedendo se ci fossero, dal momento che ho esperienza con molti meno RDBMS di quanto immaginassi la maggior parte delle persone che rispondono alle domande su questo sito;) Ma questo era il mio sospetto.
Adam Robinson,

3
"e non in nessun altro DBMS per quanto ne so." PostgreSQL 9.1 ha aggiunto una nuova funzionalità progettata per questo scopo. È più restrittivo dell'implementazione di MySQL.
Mark Byers,

@MarkByers: grazie, non lo sapevo.
ypercubeᵀᴹ

24

Oltre alla soluzione alternativa di @ ypercube, la "digitazione" non è mai una scusa per l'utilizzo SELECT *. Ho scritto su questo qui , e anche con la soluzione alternativa penso che il tuo SELECTelenco dovrebbe ancora includere i nomi delle colonne - anche se ci sono un numero enorme come 40.

Per farla breve, puoi evitare di digitare questi grandi elenchi facendo clic e trascinando il nodo Colonne per l'oggetto in Esplora oggetti nella finestra della query. La schermata mostra una vista ma la stessa cosa può essere fatta per un tavolo.

inserisci qui la descrizione dell'immagine

Ma se vuoi leggere tutti i motivi per cui dovresti sottoporti a questo enorme livello di sforzo nel trascinare un oggetto di qualche centimetro, leggi il mio post . :-)


In PostgreSQL (con EMS SQL Manager), lo faccio definendo una vista come SELECT *e quindi copio l'elenco dei campi dalla definizione della vista.
dezso,

Sono certamente d'accordo che SELECT *non dovrebbe essere usato. Sono curioso del GROUP BYcaso però. @Aaron, ci sono problemi di efficienza con 40 colonne nell'elenco Raggruppa per?
ypercubeᵀᴹ

1
@ypercube - Per quanto ho visto se il tuo gruppo da A.PK, A.some, A.other, A.columnsesso non si preoccupa effettivamente di confrontare some, other, columnsquesto è solo richiesto dalla sintassi.
Martin Smith,

1
@datagod dispiace, no, eventuali lacune possono essere spiegate solo dal team di sviluppo di SSMS. :-)
Aaron Bertrand

1
@Pacerier Siamo spiacenti, non sono completamente d'accordo , ma forse potresti elaborarlo.
Aaron Bertrand
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.