Dlaczego symbole wieloznaczne w instrukcjach GROUP BY nie działają?

29

Próbuję uruchomić następującą instrukcję SQL, ale pojawia się błąd składniowy:

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

Tutaj A jest szeroką tabelą z 40 kolumnami i chciałbym uniknąć umieszczania nazwy każdej kolumny w klauzuli GROUP BY, jeśli to możliwe. Mam wiele takich tabel, w których muszę uruchomić podobne zapytanie, więc będę musiał napisać procedurę składowaną. Jak najlepiej to podejść?

Używam MS SQL Server 2008.

Anonimowy Maximus
źródło

Odpowiedzi:

32

GROUP BY A.* nie jest dozwolone w SQL.

Możesz to obejść, używając podzapytania, w którym grupujesz, a następnie dołączasz:

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 ;

W standardzie SQL-2003 istnieje funkcja pozwalająca na SELECTliście kolumny, których nie ma na GROUP BYliście, o ile są od nich funkcjonalnie zależne. Jeśli ta funkcja została zaimplementowana w SQL-Server, twoje zapytanie mogłoby zostać zapisane jako:

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

Niestety, ta funkcja nie została jeszcze zaimplementowana, nawet w wersji SQL-Server 2012 - i o ile wiem, nie w żadnym innym DBMS. Z wyjątkiem MySQL, który ma go, ale nieodpowiednio (nieodpowiednio, ponieważ powyższe zapytanie będzie działać, ale silnik nie sprawdzi zależności funkcjonalnej, a inne źle napisane zapytania pokażą nieprawidłowe, pół losowe wyniki).

Jak @Mark Byers poinformował nas w komentarzu, PostgreSQL 9.1 dodał nową funkcję zaprojektowaną do tego celu. Jest bardziej restrykcyjny niż implementacja MySQL.

ypercubeᵀᴹ
źródło
Czy możesz wymienić kilka RDBMS, które implementują tę część standardu, jak napisano? Wiem na przykład, że MySQL pozwoli (przy odpowiednich ustawieniach) na uwzględnienie pozycji nie znajdujących się w GROUP BYklauzuli na SELECTliście, ale nie określa , z którego wiersza będzie pochodzić ta wartość (więc jeśli kolumna lub wyrażenie nie jest nie jest funkcjonalnie zależny od wyrażenia grupującego, wówczas może pochodzić z dowolnego wiersza w grupie).
Adam Robinson,
@Adam: Nie, nie znam RDBMS, który to zaimplementował. MySQL ma go, ale niewystarczająco, jak mówi twój komentarz.
ypercubeᵀᴹ
Gotcha Właściwie to pytałem, czy istnieją, ponieważ mam doświadczenie z mniejszą liczbą RDBMS, niż wyobrażam sobie większość osób odpowiadających na pytania na tej stronie;) Ale takie było moje podejrzenie.
Adam Robinson,
3
„i o ile wiem, nie w żadnym innym DBMS”. PostgreSQL 9.1 dodał nową funkcję zaprojektowaną do tego celu. Jest bardziej restrykcyjny niż implementacja MySQL.
Mark Byers,
@MarkByers: dzięki, nie wiedziałem o tym.
ypercubeᵀᴹ
24

Oprócz obejścia @ ypercube „pisanie” nigdy nie jest usprawiedliwieniem użycia SELECT *. Pisałem o tym tutaj i nawet z obejściem, myślę, że twoja SELECTlista powinna nadal zawierać nazwy kolumn - nawet jeśli jest ich ogromna liczba, np. 40.

Krótko mówiąc, można uniknąć wpisywania tych dużych list, klikając i przeciągając węzeł Kolumny dla obiektu w Eksploratorze obiektów do okna zapytania. Zrzut ekranu pokazuje widok, ale to samo można zrobić dla stołu.

wprowadź opis zdjęcia tutaj

Ale jeśli chcesz przeczytać o wszystkich powodach, dla których powinieneś poddać się tak ogromnemu wysiłkowi przeciągania elementu o kilka cali, przeczytaj mój post . :-)

Aaron Bertrand
źródło
W PostgreSQL (z EMS SQL Manager) robię to, definiując widok jako, SELECT *a następnie kopiuję listę pól z definicji widoku.
dezso
Z pewnością zgadzam się, że SELECT *nie należy tego używać. Ciekawi mnie jednak GROUP BYsprawa. @Aaron, czy występują problemy z wydajnością związane z posiadaniem 40 kolumn na liście Grupuj według?
ypercubeᵀᴹ
1
@ypercube - O ile widziałem, jeśli grupujesz według A.PK, A.some, A.other, A.columnstego, to nie przeszkadza, że ​​porównanie some, other, columnsjest wymagane tylko przez składnię.
Martin Smith
1
@datagod przepraszam, nie, wszelkie luki mogą być wyjaśnione tylko przez zespół deweloperów SSMS. :-)
Aaron Bertrand
1
@Pacerier Przepraszamy, całkowicie się nie zgadzam , ale może mógłbyś to rozwinąć.
Aaron Bertrand