Informacje o nowych artykułach oraz akcjach edukacyjnych prosto na Twojej skrzynce e-mail!

Grupowanie danych: Klauzula HAVING w SQL cz. IV

Klauzula HAVING w SQL według ogólnego wzoru zapytań SELECT podanego w artykule „Podstawowa wersja zapytania SELECT w SQL (SELECT … FROM … WHERE …)” wykonywana jest po klauzuli GROUP BY, czyli po pogrupowaniu danych. Działa ona w zasadzie tak samo jak słowo kluczowe WHERE, z takim wyjątkiem, że przy WHERE nie mogliśmy używać funkcji grupującychfunkcji rankingu oraz operować na pogrupowanych danych. W klauzuli HAVING jest to wszystko dopuszczalne. W skrócie funkcja ta może zostać wykorzystana na przykład do wyeliminowania grup danych, które nie spełniają podanego po niej warunku logicznego.

Ogólna składnia zapytania SELECT zawierającego klauzulę HAVING:

SELECT kolumna1, kolumna2 FROM tabela
GROUP BY kolumna3
HAVING kolumna4 > 10; --warunek logiczny

Tabela klienci na której będziemy uruchamiać przykładowe zapytania:

IDImieNazwiskoMiasto
1JanKowalskiWarszawa
2MichałŁagodaKraków
3MarcinKulczykKraków
4RadosławSikorskiKraków
5MonikaKopaczGdańsk
6PiotrGrabiecToruń
7EwaPogodnaBydgoszcz
8SebastianSzybkiWarszawa

Pobierzmy z tabeli klienci miasta z których mamy przynajmniej dwóch klientów:

SELECT Miasto FROM klienci
GROUP BY Miasto
HAVING COUNT(*) > 1;

Efekt:

Miasto
Kraków
Warszawa

A teraz wykonajmy to samo zapytanie tylko zamiast HAVING użyjmy WHERE:

SELECT miasto FROM klienci
WHERE COUNT(*) > 1 -- BŁĄD!!!
GROUP BY miasto;

Oczywiście otrzymaliśmy błąd, gdyż jak wspomniałem na początku w klauzuli WHERE nie można używać funkcji grupujących i rankingowych.

Pobierzmy informacje o miastach w których mamy klienta o imieniu „Radosław”:

SELECT imie, nazwisko, miasto FROM klienci
GROUP BY miasto
HAVING imie = 'Radosław';

Efekt:

ImieNazwiskoMiasto
RadosławSikorskiKraków

Jak można się zorientować przerabiając powyższe przykłady, dane w naszym zapytaniu są najpierw grupowane, a potem wywoływana jest klauzula HAVING. Gdybyśmy użyli słowo kluczowe WHERE, to było by dokładnie na odwrót czyli grupowali byśmy tylko przefiltrowane wyniki co w niektórych przypadkach mogło by nam dać złe dane.

Spodobało się?

Jeśli tak, to zarejestruj się do newslettera aby otrzymywać informacje nowych artykułach oraz akcjach edukacyjnych. Gwarantuję 100% satysfakcji i żadnego spamowania!

, , , , ,

Dodaj komentarz

Komentarze (5)

  • Kordian Bober pisze:

    dobry artykuł. Przystępnie opisane

  • Radziwil pisze:

    Czy możemy wykonać takie zapytanie?

    SELECT id
    FROM klienci
    GROUP BY id
    HAVING imie = 'Radosław’;

    • Hej,

      Ale co to miało by robić? Id jest unikalne dla każdego rekordu. Po co to grupowanie wtedy?

      Łukasz Dudziński

      • Radziwil pisze:

        Hej

        Potrzeba pobrania wszystkich ID, kiedy w kolumna imie = 'Radosław’. Poszukuję rozwiązania dla mojego przypadku, tj. pobrania wszystkich ID (jest to wynik podzapytania), kiedy np. ID pracownika występuje więcej niż jeden raz. Takie zapytanie jest poprawne:

        select tab1.idprac, count (tab1.idprac)
        from tab1
        where tab1.data1 between to_date (’2023-01-01′, 'YYYY-MM-DD’) and to_date (’2023-03-31′, 'YYYY-MM-DD’)
        group by tab1.idprac
        having count (tab1.idprac) > '1′;

        Moją intencją jest uzyskanie takiego wyniku

        select tab1.num_ewid, tab1.data1
        from tab1
        where tab1.id in (
        select tab1.id
        from tab1
        where tab1.data1 between to_date (’2023-01-01′, 'YYYY-MM-DD’) and to_date (’2023-03-31′, 'YYYY-MM-DD’)
        group by tab1.idprac
        having count (tab1.idprac) > '1′);

        Taki zapis jest nie prawidłowy.
        Moją potrzebą jest wyświetlić dla kolumn num_ewid oraz data1 wszystkie rekordy, dla których w zadanym przedziale czasu idprac występuje więcej niż jeden raz.

        Pozdrawiam
        Darek

      • Cześć Darek,

        Jeśli możesz wklej tutaj strukturę tabeli z której chcesz wyciągnąć dane.

        Pozdrawiam,
        Łukasz Dudziński, autor bloga Strefakodera.pl

Odpowiedz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Pin It on Pinterest