Krótki przegląd zapytań



Podobne dokumenty
W tej części zajmiemy się ćwiczeniami dotyczącymi modyfikacji rekordów.

Relacyjne bazy danych. Podstawy SQL

Przykłady najlepiej wykonywać od razu na bazie i eksperymentować z nimi.

77. Modelowanie bazy danych rodzaje połączeń relacyjnych, pojęcie klucza obcego.

Język SQL, zajęcia nr 1

Ćwiczenia laboratoryjne nr 11 Bazy danych i SQL.

Laboratorium nr 4. Temat: SQL część II. Polecenia DML

Wykład 6. SQL praca z tabelami 3

Relacyjne bazy danych. Podstawy SQL

Wykład 05 Bazy danych

Bazy danych. Bazy danych. Podstawy języka SQL. Dr inż. Paweł Kasprowski.

Autor: Joanna Karwowska

Laboratorium nr 8. Temat: Podstawy języka zapytań SQL (część 2)

Przestrzenne bazy danych Podstawy języka SQL

Laboratorium nr 5. Temat: Funkcje agregujące, klauzule GROUP BY, HAVING

Wstęp 5 Rozdział 1. Podstawy relacyjnych baz danych 9

1. Tworzenie tabeli. 2. Umieszczanie danych w tabeli

Język SQL, zajęcia nr 2

Wykład 5. SQL praca z tabelami 2

Projekt jest finansowany ze środków Unii Europejskiej, Europejskiego Funduszu Społecznego i budŝetu państwa. Studia Podyplomowe dla Nauczycieli

Struktura drzewa w MySQL. Michał Tyszczenko

Wykład 8. SQL praca z tabelami 5

Podstawowe zapytania SELECT (na jednej tabeli)

Bazy Danych - Instrukcja do Ćwiczenia laboratoryjnego nr 8

Bazy danych. Polecenia SQL

Podstawy języka SQL. SQL Structured Query Languagestrukturalny

Autor: Joanna Karwowska

Autor: Joanna Karwowska

Język SQL Złączenia. Laboratorium. Akademia Morska w Gdyni

Integralność danych Wersje języka SQL Klauzula SELECT i JOIN

PRZESTRZENNE BAZY DANYCH WYKŁAD 2

Wykład 7 Implementacja języka SQL w systemach baz danych Oracle sortowanie, funkcje agregujące i podzapytania.

Aby uruchomić program klienta i połączyć się z serwerem, należy komendę:

Systemy GIS Tworzenie zapytań w bazach danych

Laboratorium nr 10. Temat: Połączenia relacji

Projektowanie systemów baz danych

Bazy danych. Dr inż. Paweł Kasprowski

SIECI KOMPUTEROWE I BAZY DANYCH

Programowanie MSQL. show databases; - pokazanie jakie bazy danych są dostępne na koncie

SQL (ang. Structured Query Language)

strukturalny język zapytań używany do tworzenia i modyfikowania baz danych oraz do umieszczania i pobierania danych z baz danych

Bazy danych. dr inż. Arkadiusz Mirakowski

Konstruowanie Baz Danych SQL UNION, INTERSECT, EXCEPT

Podstawy języka SQL. standardy SQL formułowanie zapytań operacje na strukturach danych manipulowanie danymi. Bazy danych s.5-1

Wprowadzenie do baz danych

Przykładowa baza danych BIBLIOTEKA

Autor: Joanna Karwowska

koledzy, Jan, Nowak, ul. Niecała 8/23, , Wrocław, , ,

Bazy danych. Wykład IV SQL - wprowadzenie. Copyrights by Arkadiusz Rzucidło 1

Język SQL. instrukcja laboratoryjna. Politechnika Śląska Instytut Informatyki. laboratorium Bazy Danych

SQL Server i T-SQL w mgnieniu oka : opanuj język zapytań w 10 minut dziennie / Ben Forta. Gliwice, Spis treści

Zadania z SQLa (MS SQL Server)

Wprowadzenie do projektowania i wykorzystania baz danych Relacje

Instytut Mechaniki i Inżynierii Obliczeniowej fb.com/groups/bazydanychmt/

Bazy danych 2. Wykład 4 Structured Query Language (SQL)

CREATE DATABASE ksiegarnia_internetowa DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

Wykład 4. SQL praca z tabelami 1

SQL - Structured Query Language -strukturalny język zapytań SQL SQL SQL SQL

Informatyka sem. III studia inżynierskie Transport 2018/19 LAB 2. Lab Backup bazy danych. Tworzenie kopii (backup) bazy danych

Bazy danych SQL Server 2005

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny Technologiczny Politechnika Śląska

Kurs. Podstawy MySQL

Laboratorium Bazy danych SQL 2

Paweł Rajba

Ref. 7 - Język SQL - polecenia DDL i DML

Języki programowania wysokiego poziomu. PHP cz.4. Bazy danych

Grupowanie i funkcje agregujące

Tworzenie tabel. Bazy danych - laboratorium, Hanna Kleban 1

Instytut Mechaniki i Inżynierii Obliczeniowej fb.com/groups/bazydanychmt/

Bazy danych 7. SQL podstawy

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny technologiczny Politechnika Śląska

P o d s t a w y j ę z y k a S Q L

Program szkoleniowy Efektywni50+ Moduł IV Podstawy relacyjnych baz danych i język SQL

Instytut Mechaniki i Inżynierii Obliczeniowej Wydział Mechaniczny technologiczny Politechnika Śląska

Wykład 5: PHP: praca z bazą danych MySQL

Ćwiczenie 3 funkcje agregujące

Instalacja MySQL.

BAZY DANYCH wprowadzenie do języka SQL. Opracował: dr inż. Piotr Suchomski

Bazy Danych. SQL Podstawy języka III: powtórzenie. Krzysztof Regulski WIMiIP, KISiM, B5, pok. 408

TEST E.14 BAZY DANYCH

NARZĘDZIA WIZUALIZACJI

opisuje nazwy kolumn, wyrażenia arytmetyczne, funkcje nazwy tabel lub widoków warunek (wybieranie wierszy)

Literatura: SQL Ćwiczenia praktyczne Autor: Marcin Lis Wydawnictwo: Helion. Autor: Joanna Karwowska

- język zapytań służący do zapisywania wyrażeń relacji, modyfikacji relacji, tworzenia relacji

Bazy danych. Bazy danych. Zapytania SELECT. Dr inż. Paweł Kasprowski.

Wykład 5 Charakterystyka języka SQL. Elementy obliczeń relacyjnych.

Podstawowe funkcje dodatku linq w C#

1 DML - zapytania, część II Grupowanie Operatory zbiorowe DML - modyfikacja 7. 3 DCL - sterowanie danymi 9.

Kwerendy (zapytania) wybierające

Zapytania do bazy danych

Ćwiczenie zapytań języka bazy danych PostgreSQL

15. Funkcje i procedury składowane PL/SQL

Technologie informacyjne lab. 2: Bazy danych

Programowanie w Ruby

Widok Connections po utworzeniu połączenia. Obszar roboczy

Wstęp do SQL. copyright: KGiIS WGGiOŚ AGH

SQL - Structured Query Language. strukturalny język zapytań

Transkrypt:

Krótki przegląd zapytań NajwaŜniejszą rzeczą jest uświadomienie sobie, Ŝe baza danych to generalnie zestaw tabel a więc stosunkowo prostych obiektów, składających się z wierszy i kolumn. Wszelkie operatory, wszelkie zapytania kierowane do bazy odnoszą się do tabel. Kolumny tabeli mają określone typy to oznacza, Ŝe jeśli zdefiniujemy taką kolumnę na przykład jako int (liczba całkowita), to nie będziemy mogli w niej przechowywać innych danych (np. napisów, albo liczb rzeczywistych). Oprócz typów, kolumnę mogą cechować dodatkowe ograniczenia (uzaleŝnione od typu). Przykładem takiego ograniczenia jest np. klauzule UNIQUE (która mówi, Ŝe wartości w tej kolumnie nie mogą się powtarzać), lub NOT NULL (baza nie zaakceptuje wartości nieustawionej, czyli pustej). Tworzenie tablic w bazie odbywa się za pomocą polecenia CREATE TABLE. W tym miejscu warto zauwaŝyć, Ŝe nie wszystkie bazy danych implementują dokładnie stuprocentowo standard SQL. Dzieje się tak dlatego, Ŝe podstawowy SQL okazał się językiem dość ograniczonym i wielu najwaŝniejszych dostawców postanowiło zaoferować dodatki, które ułatwiają pracę twórcom baz danych. W ten sposób powstały tzw. dialekty SQL wersje podstawowego języka, które minimalnie się od siebie róŝnią. PoniŜsze przykłady dotyczą SQL w wersji mysql. Na przykład: CREATE TABLE student (imie char(50), nazwisko char(50)) Powoduje utworzenie tabeli student (wielkość liter nie ma znaczenia) o dwóch kolumnach: imie i nazwisko w obu przechowujemy ciągi znakowe o długości do 50 znaków. Średnik na końcu polecenia jest znakiem charakterystycznym dla silnika mysql (nie jest częścią zapytania SQL). Formuła Query OK jest informacją zwrotną serwera mysql o poprawnym wykonaniu polecenia. Spróbujmy dodać kilka rekordów. MoŜemy to zrobić poleceniem INSERT INTO... VALUES: INSERT INTO student (imie, nazwisko) VALUES ( Jan, Kowalski ); Po wypełnieniu kilkoma rekordami przykładowymi, tabela moŝe wyglądać tak: Jan Maria Tadeusz Julia Magda Iwona Paulina Kowalski Nowak Malinowski Kowalczyk Jakubowska Krzewska Rydygier Oczywiście odpowiada to takiemu modelowi encji: Imię Nazwisko STUDENT

Sprawdźmy teraz, jakie rekordy znajdują się w naszej bazie danych. SELECT, a najprostsza jego składnia wygląda tak: SłuŜy do tego polecenie SELECT [kolumny] FROM [tabela] Kolumny mogą przyjąć postać nazwy, nazw rozdzielanych przecinkiem lub *, która oznacza: wszystkie. Sprawdźmy. W tym celu wykonamy polecenie: SELECT * FROM student Oczywiście moglibyśmy teŝ wykonać: SELECT imie, nazwisko FROM student W tym miejscu jedna uwaga: zastosowany w przykładzie klient mysql (czyli oprogramowanie, którym łączymy się z bazą) domyślnie umieszcza w prezentowanym na ekranie wyniku nazwy kolumn. To nie jest zachowanie zgodne z SQL jedynie pomoc dla uŝytkownika. Wynikiem zapytania są jedynie wartości pól, czyli tabela: Jan Maria Tadeusz Julia Magda Iwona Paulina Kowalski Nowak Malinowski Kowalczyk Jakubowska Krzewska Rydygier Oczywiście moŝemy takŝe poprosić bazę danych o same nazwiska:

Istnieje sposób ograniczenia wyników zapytania SELECT. SłuŜy do tego klauzula WHERE, która jest swego rodzaju filtrem. Oznacza ona, Ŝe serwer bazy danych najpierw wykona (na własne potrzeby) zwykłe SELECT, a następnie wyświetli (zwróci) jedynie te rekordy, które pasują do warunku podanego w WHERE. Przykład: W tym miejscu zauwaŝmy, Ŝe warunki dla klauzuli WHERE budujemy najczęściej w oparciu o operatory = (równość) <> (róŝność) i > (większość). W przypadku łańcuchów tekstowych mamy takŝe często uŝywany operator LIKE (podobny do), stosowany wraz ze znakiem specjalnym % (zastępuje dowolny ciąg znaków, działa jak * przy wyszukiwaniu plików w Windows). W ten sposób mamy: RóŜność łańcuchów: Operator większości (dla liczb działa jak porównanie arytmetyczne, dla łańcuchów znakowych jak porównanie alfabetyczne): Zwróćmy uwagę, Ŝe operator podobieństwa nie zadziała dobrze, jeśli nie zastosujemy znaku %. Ściślej: zadziała wówczas, jak operator równości (a w bazie nie ma osoby o imieniu na : Wyszukujemy wszystkich tych, których imiona kończą się na na :

Drugą waŝną klauzulą dla SELECT jest ORDER BY, czyli sortowanie. MoŜe ona być zastosowana samodzielnie lub razem z WHERE. Jeśli chodzi o kolejność poszczególnych elementów zapytania, to waŝne jest, aby pamiętać, jak ono w rzeczywistości jest wykonywane przez serwer. Popatrzmy na ostatnie zapytanie: SELECT * FROM student WHERE nazwisko LIKE K% ORDER BY nazwisko. Na początku serwer wykona zwykłego selecta: SELECT * FROM student, otrzymując 7 rekordów. Z rekordów tych zostaną wyfiltrowane tylko te, w których nazwisko zaczyna się na literę K. Otrzymane 3 rekordy zostaną posortowane względem nazwiska. Dlatego zapytanie SELECT * ORDER BY nazwisko WHERE nazwisko LIKE K% nie ma sensu (jest błędne). ZałóŜmy, Ŝe chcemy naszą tabelę rozszerzyć o nową kolumnę będzie nią wzrost. Jest to oczywiście liczba int. Do modyfikacji istniejącej tabeli słuŝy polecenie ALTER TABLE. Oczywiście moŝna najpierw usunąć tabelę, potem stworzyć nową i ponownie wypełnić wartości ale to zbyt skomplikowana droga.

Jak widać, w tabeli pojawiła się nowa kolumna. KaŜdy rekord ma pole wzrost równe NULL. NULL jest specjalną wartością, która moŝe pojawić się w kolumnie dowolnego typu. Oznacza ona wartość nieustaloną i nie naleŝy jej mylić z wartością zerową. To tak jak z posiadaniem samochodu. Sytuacja, w której Kowalski NIE MA samochodu, to nie jest to samo, co sytuacja, w której NIE WIEMY, czy Kowalski ma samochód. W wersji SQL Kowalski ma 0 samochodów lub ma NULL samochodów. Aby ustawić wartość pola istniejącego rekordu, posłuŝymy się poleceniem UPDATE. Jedna bardzo waŝna uwaga UPDATE zmienia wartość wszystkich rekordów, których dotyczy, dlatego trzeba dokładnie określać zakres jego działania. Najczęstszy błąd początkującego bazodanowa wygląda tak (zakładamy, Ŝe chcieliśmy zmienić pierwszy rekord): W tym miejscu zauwaŝamy z przeraŝeniem, Ŝe wszystkie rekordy uległy modyfikacji! Aby zmodyfikować wyłącznie wzrost Jana Kowalskiego powinniśmy posłuŝyć się poleceniem UPDATE z klauzulą WHERE: ZałóŜmy, Ŝe po wykonaniu kilku poleceń UPDATE tabela wygląda tak:

KaŜdy praktyk bazodanowy wie, Ŝe wygodnie mieć specjalną kolumnę słuŝącą do unikalnej identyfikacji rekordów. Taka kolumna odpowiadałaby kluczowi głównemu encji, której realizacją jest tabela. Najprościej taką kolumnę utworzyć jako kolumnę liczb int (całkowitych) i poinformować silnik bazy danych, Ŝeby samodzielnie dbał o niepowtarzalność jej wartości. W mysql dokonuje się tego za pomocą ograniczeń AUTO_INCREMENT i PRIMARY KEY (w innych bazach moŝe to wyglądać trochę inaczej). Spróbujmy więc: ZauwaŜmy, Ŝe w przeciwieństwie do poprzedniego ALTER TABLE, teraz nowa kolumna zawiera juŝ wartości. Dzieje się tak dzięki AUTO_INCREMENT, które automatycznie dodaje nowe wartości). ZauwaŜmy teŝ, Ŝe baza danych nie pozwala nam na wpisanie nowego rekordu z jednoczesnym określeniem wartości pola id (o ile wartość id łamie warunek unikalności): W praktyce najlepiej w ogóle nie ustawiać pola, którym ma się zajmować baza danych: Jak widać, pole ustawiło się samo:

Dlaczego w polu id jest wartość 11, a nie 8? Dlatego, Ŝe w międzyczasie wykonano na bazie kilka operacji m.in. wstawienie i usunięcie rekordu w tablicy student. Autoinkrementacja nie działa zawsze tak, Ŝe nowa wartość zwiększa się o 1! Co więcej, jeśli usuniemy rekord o id=2, to nowotworzony student nie dostanie brakującego identyfikatora. Dzieje się tak z powodów bezpieczeństwa mogłoby dojść do sytuacji, w których taki nowy rekord zostałby powiązany z nieusuniętymi danymi powiązanymi. Powiemy o tym dalej. Rozbudujmy naszą bazę danych o kolejne encje. Jedna z nich będzie powiązana relacją wiele-dowiele, a druga jeden-do-wiele. Oczywiście, w tym pierwszym przypadku potrzebna będzie nam dodatkowa tabela: Imię Nazwisko Nazwa Id Id STUDENT MIASTO PRZEDMIOT KOD Id Nazwa Popatrzym na powyŝszy diagram ERD. Widzimy, Ŝe nasz STUDENT jest powiązany z encją MIASTO. Jest to miasto, w którym się urodził. Oczywiście kaŝdy STUDENT moŝe się urodzić tylko w jednym mieście, ale kaŝde miasto moŝe się pochwalić wieloma studentami jest to relacja 1-do-wielu. Popatrzmy na encję PRZEDMIOT. KaŜdy STUDENT moŝe uczęszczać na wiele PRZEDMIOTÓW, a kaŝdego z PRZEDMIOTÓW moŝe się uczyć wielu STUDENTÓW. Stąd teŝ mamy relację wiele-dowiele. Oznacza to, Ŝe musimy wprowadzić dodatkową tabelę dla przechowywania informacji o relacji.

imię nazwisko nazwa id Id_m id STUDENT id_s MIASTO STUPRZ id id_p PRZEDMIOT kod id nazwa Przyjrzyjmy się zmianom na diagramie ERD. Po pierwsze, pojawiły się atrybuty zaznaczone kolorem. Są to tak zwane klucze zewnętrzne, czyli takie, które są kluczami głównymi w innych tabelach. Po drugie pojawiła się dodatkowa tabele STUPRZ, która odpowiada relacji wiele do wiele pomiędzy encjami STUDENT i PRZEDMIOT. Pole id w tej tabeli nie jest wymagane, ale jest dobrą praktyką bazodanową o czym będziemy wspominać dalej. Tworzymy potrzebne nam tabele (na razie w najprostszej moŝliwej wersji): Oczywiście w tabeli STUPRZ pola id_s i id_m nie mają autoinkrementacji bo nie są to klucze główne! ZałóŜmy, Ŝe nasze nowe tablice wyglądają tak:

Po pierwsze, zastanówmy się, jak reprezentowane są związki pomiędzy elementami encji. Popatrzymy na Jana Kowalskiego. Pole id_m tego rekordu zawiera wartość 1. PoniewaŜ jest to klucz zewnętrzny z tabeli MIASTO, szukamy w tej tabeli rekordu o id=1. Wynika z niego, Ŝe Jan Kowalski pochodzi z Gdańska. Sprawdźmy, na jakie przedmioty zapisany jest ten student? PoniewaŜ encje STUDENT i PRZEDMIOT są związane relacją wiele-do-wiele, szukamy w tablicy STUPRZ tych rekordów, których pole id_s=1. Jak widać, Jan Kowalski jest zapisany na zajęcia z Programowania 1, Symulacji, Programowania 2 i Baz Danych. Powróćmy do prostszej relacji tej, która łączy tabele STUDENT i MIASTO. Jak uzyskać informację o wszystkich studentach wraz z miastami ich pochodzenia? Po pierwsze, moŝemy wykorzystać zapytanie SELECT działające na 2 tabelach. Spróbujmy więc:

Jak widać, dostajemy dość nieoczekiwane wyniki. Dzieje się tak dlatego, Ŝe SELECT wykonany na dwóch (i więcej) tabelach polega na utworzeniu wszystkich moŝliwych kombinacji rekordów z pierwszej i drugiej tabeli. Jest to tak zwany iloczyn kartezjański. 1, Jan, Kowalski, 1, Gdańsk 4, Julia, Kowalczyk, 2, Poznań

Oczywiście nie wszystkie z 32 rekordów wynikowych mają sens. Powinniśmy wyfiltrować z uzyskanego zbioru te, dla których wartość pola id_m w tabeli STUDENT odpowiada pewnemu id w tabeli MIASTO. Jak wcześniej wspomnieliśmy, do filtrowania wyników słuŝy klauzula WHERE: Jak widać, zapytanie się nie udaje. Dzieje się tak dlatego, Ŝe baza danych nie jest pewna, czy warunek id_m=id dotyczy pola id z tabeli STUDENT, czy z tabeli MIASTO. Wprowadzamy więc dodatkowo oznaczenie tabeli: Zapytanie łączące w ten sposób kilka tabel mogłoby być dość trudne do przeczytania i poprawnego zinterpretowania, dlatego SELECT * FROM tabela1, tabela2 WHERE tabela1.kolumna1 = tabela2.kolumna2 zapisuje się w postaci (jest to tak zwany INNER JOIN): SELECT * FROM tabela1 JOIN tabela2 ON (tabela1.kolumna1 = tabela2.kolumna2) Na pierwszy rzut oka moŝe to wyglądać na wprowadzenie dodatkowego zamieszania, ale jak się potem przekonamy wbrew pozorom wcale tak nie jest. Jak widzimy, widać juŝ poprawne wyniki. Jest tylko jeden problem na liście brakuje 2 studentów! Dzieje się tak dlatego, Ŝe warunek id_m=id wymaga, Ŝeby istniały odpowiednie wartości w kolumnach id_m i id, tymczasem dla dwóch studentów (Paulina i Krzysztof) nie określono wartości id_m (wartość wynosi NULL). Podobny problem występuje z miastami nie widać na liście Krakowa.

id_m = 1, id = 1 czyli id_m=id id_m = 1, id = 1 czyli id_m=id id_m = 2, id = 2 czyli id_m=id id_m = 2, id = 2 czyli id_m=id id_m = 3, id = 3 czyli id_m=id id_m = 3, id = 3 czyli id_m=id id_m = NULL, id = 4 czyli id_m<>id id_m = NULL, id = 2 czyli id_m<>id Naszym celem jest teraz przygotowanie listy studentów, wraz z miastami ich pochodzenia (lub wartością NULL, gdy jest ono nieznane). UŜywamy do tego tak zwanego złączenia OUTER JOIN. PoniewaŜ zaleŝy nam na dopuszczeniu wartości NULL po stronie tablicy STUDENT, stosujemy tak zwany OUTER LEFT JOIN (bo tablica STUDENT jest po lewej stronie): Wersja RIGHT OUTER JOIN dopuszcza wartości NULL (w tym przypadku nie istniejące) po stronie prawej: Niektóre bazy danych (nie wszystkie) dopuszczają takŝe tzw. pełny OUTER JOIN który jest połączeniem LEFT OUTER i RIGHT OUTER. Kiedy potrafimy juŝ efektywnie łączyć tablice bazy danych, moŝemy pokusić się o wprowadzenie nowej funkcjonalności agregowania i grupowania.

Agregowanie to wyliczanie pewnej wartości (jednej) dla całego zbioru danych. Zacznijmy od prostego przykładu policzmy, jaki jest największy wzrost w grupie studenckiej. SłuŜy do tego funkcja agregująca max(): ZauwaŜmy, Ŝe w odróŝnieniu od klasycznego SELECT nie wskazujemy bezpośrednio kolumny (wzrost), ale przeprowadzamy na niej operację max(). MoŜemy takŝe wyliczyć wartość najmniejszą min(), średnią avg() lub zliczyć elementy funkcją count(): MoŜliwe jest takŝe wyliczanie kilku agregatów jednocześnie: Spróbujmy teraz połączyć dwa elementy: łączenie tablic ze zliczaniem elementów. Spróbujmy policzyć studentów we wszystkich miastach. Zacznijmy od wyznaczenia wszystkich miast i pochodzących z nich studentów: Nie jest to jednak najlepsza droga - interesują nas bowiem tylko miasta i liczba studentów (a nie ich nazwiska). Dlatego pozbędziemy się zbędnej kolumny:

Teraz wystarczy pogrupować miasta i policzyć je: Jak widać, nasze zapytanie rozbudowaliśmy o dwa elementy: wskazaliśmy, Ŝe chcemy liczyć identyfikatory studentów ( count(student.id) ) i zaŝądaliśmy, aby grupować studentów według miast (GROUP BY nazwa). Otrzymaliśmy w wyniku tabelę czasami warto jednak móc ją dalej filtrować, na przykład po to, aby wyznaczyć miasta, z liczbą studentów równą 0. Zwykle do filtrowania uŝywaliśmy klauzuli WHERE tu jednak nie moŝemy jej uŝyć, bowiem mogło się przecieŝ zdarzyć, Ŝe uŝyjemy ją wcześniej. Na przykład, gdybyśmy chcieli wyznaczyć listę miast ze studentami ale tylko tych miast, które zawierają w nazwie literę k): PowyŜsze zapytanie jest dość abstrakcyjne (Ŝeby nie powiedzieć: dziwaczne), ale dobrze pokazuje, dlaczego nie moŝemy uŝyć WHERE do filtrowania efektów GROUP BY. W rezultacie, Ŝeby moŝna było filtrować efekty grupowania, uŝywa się dodatkowej klauzuli: HAVING:

To zapytanie pokazuje wszystkie te miasta, które w nazwie mają literę K, dla których liczba studentów jest równa 2. Warto zapamiętać: HAVING filtruje wyniki GROUP BY tak, jak WHERE filtruje wyniki SELECT. Nie moŝna stosować HAVING do wyników zwykłego SELECT, tak samo, jak nie moŝna filtrować GROUP BY za pomocą WHERE.