2010-02-25 16 views
70

Używam MySQL. Oto mój schemat:MySQL: Niewłaściwe użycie funkcji grupy

Dostawcy (SID: Integer, sname: string, adres string)

części (PID: całkowite, PNAME: String, kolor: String)

katalogowa (SID: całkowita, PID: całkowita, koszt real)

(klucze główne są pogrubione)

ja t uszenie napisać kwerendę, aby wybrać wszystkie elementy, które są wykonane przez co najmniej dwóch dostawców:

-- Find the pids of parts supplied by at least two different suppliers. 
SELECT c1.pid      -- select the pid 
FROM Catalog AS c1     -- from the Catalog table 
WHERE c1.pid IN (     -- where that pid is in the set: 
    SELECT c2.pid     -- of pids 
    FROM Catalog AS c2    -- from catalog 
    WHERE c2.pid = c1.pid AND COUNT(c2.sid) >= 2 -- where there are at least two corresponding sids 
); 

Po pierwsze, mam nawet zamiar o tym właściwą drogę?

Po drugie, pojawia się ten błąd:

1111 - Invalid use of group function

Co robię źle?

Odpowiedz

120

Musisz użyć HAVING, a nie WHERE.

Różnica jest następująca: klauzula WHERE filtruje wiersze, które wybiera MySQL. Następnie MySQL grupuje wiersze i agreguje liczby dla Twojej funkcji COUNT.

HAVING jest jak WHERE, tylko zdarza się po została obliczona wartość COUNT, więc będzie działać zgodnie z oczekiwaniami. Przepisz swoje podkwerendy jako:

(     -- where that pid is in the set: 
SELECT c2.pid     -- of pids 
FROM Catalog AS c2    -- from catalog 
WHERE c2.pid = c1.pid 
HAVING COUNT(c2.sid) >= 2) 
+1

Więc "HAVING" liczy się najpierw, a następnie filtry, czy tak? –

+15

Również jeśli użyto GROUP BY, HAVING powinno być po GROUP BY – Viacheslav

+0

Również GROUP BY musi być przed HAVING .... Powinien przeczytać komentarz Bandolero: D – Andrew

4

Po pierwsze, błąd, który otrzymujesz, wynika z miejsca, w którym używasz funkcji COUNT - nie możesz użyć funkcji agregującej (lub grupowej) w klauzuli WHERE.

Po drugie, zamiast za pomocą podzapytania, wystarczy dołączyć tabelę do siebie:

SELECT a.pid 
FROM Catalog as a LEFT JOIN Catalog as b USING(pid) 
WHERE a.sid != b.sid 
GROUP BY a.pid 

który moim zdaniem powinien zwrócić tylko wiersze, gdzie istnieją przynajmniej dwa wiersze z tego samego pid ale istnieje co najmniej 2 sid s. Aby upewnić się, że wrócisz tylko jeden wiersz na pid Zastosowałem klauzulę grupowania.

+0

Czy to możliwe, że nie potrzebuję nawet dołączyć? (zobacz moją zaktualizowaną odpowiedź, gdzie dostarczyłem możliwe rozwiązanie.) –

+0

@Rosarch, myślę, że będziesz chciał użyć 'COUNT (DISTINCT sid)' w zaktualizowanym zapytaniu. –

+0

Czy "sid" nie zawsze musi być odróżniany, ponieważ 'sid' i' pid' razem tworzą klucz podstawowy dla 'Katalogu'? –

Powiązane problemy