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
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY 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ść?
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
LEFTJOIN(SELECT FKey, COUNT(foo)AS cnt
FROM TABLE2
GROUPBY 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
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY 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).
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.
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 . :-)
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. :-)
GROUP BY
klauzuli naSELECT
liś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).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 twojaSELECT
lista 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.
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 . :-)
źródło
SELECT *
a następnie kopiuję listę pól z definicji widoku.SELECT *
nie należy tego używać. Ciekawi mnie jednakGROUP BY
sprawa. @Aaron, czy występują problemy z wydajnością związane z posiadaniem 40 kolumn na liście Grupuj według?A.PK, A.some, A.other, A.columns
tego, to nie przeszkadza, że porównaniesome, other, columns
jest wymagane tylko przez składnię.