W bazie SQLite3 zapisanej w pliku portal.db znajdują się dane dotyczące użytkowników pewnego portalu internetowego. Plik pobieramy i zapisujemy w wybranym katalogu.
Do wykonywania operacji na bazie danych w tym materiale wykorzystamy skrypt napisany w języku Python oraz moduł sqlite3 przeznaczony do obsługi baz SQLite3.
Podstawy pracy z bazą danych z wykorzystaniem skryptów Pythona zostały omówione w materiale Instrukcje wyszukiwania w języku SQL, etap IIIPkQh27XjUInstrukcje wyszukiwania w języku SQL, etap III.
Ponieważ pracujemy na bazie SQLite3, instrukcje SQL zamieszczone w tym materiale możemy również wykonywać:
Poznajmy zawartość bazy. W wybranym edytorze tworzymy skrypt, w którym umieszczamy następujący kod:
Linia 1. import sqlite3.
Linia 3. def wykonaj podkreślnik zapytanie otwórz nawias okrągły kursor przecinek zapytanie zamknij nawias okrągły dwukropek.
Linia 4. kursor kropka execute otwórz nawias okrągły zapytanie zamknij nawias okrągły.
Linia 5. for rekord in kursor kropka fetchall otwórz nawias okrągły zamknij nawias okrągły dwukropek.
Linia 6. print otwórz nawias okrągły asterysk rekord zamknij nawias okrągły.
Linia 8. baza znak równości apostrof portal kropka db apostrof.
Linia 9. pol znak równości sqlite3 kropka connect otwórz nawias okrągły baza zamknij nawias okrągły kratka połączenie z bazą.
Linia 10. kursor znak równości pol kropka cursor otwórz nawias okrągły zamknij nawias okrągły kratka utworzenie obiektu kursora.
Linia 12. kwerenda znak równości cudzysłów SELECT name przecinek sql FROM sqlite podkreślnik master WHERE type znak równości apostrof table apostrof średnik cudzysłów.
Linia 14. wykonaj podkreślnik zapytanie otwórz nawias okrągły kursor przecinek kwerenda zamknij nawias okrągły.
import sqlite3
def wykonaj_zapytanie(kursor, zapytanie):
kursor.execute(zapytanie)
for rekord in kursor.fetchall():
print(*rekord)
baza = 'portal.db'
pol = sqlite3.connect(baza) # połączenie z bazą
kursor = pol.cursor() # utworzenie obiektu kursora
kwerenda = "SELECT name, sql FROM sqlite_master WHERE type='table';"
wykonaj_zapytanie(kursor, kwerenda)
Do nawiązania połączenia z bazą wykorzystujemy metodę connect(). Przekazujemy jej nazwę pliku, w którym zapisana jest baza. Wykonywanie operacji na bazie umożliwia obiekt kursora zwracany przez metodę cursor(). Kursor udostępnia metodę execute() pozwalającą wykonywać zapytania SQL podane jako argument. Wyniki zapytania zwraca w postaci listy rekordów metoda fetchall().
Plik zapisujemy pod nazwą kwerendy_portal.py w tym samym katalogu, w którym zapisaliśmy wcześniej bazę danych.
Polecenie 1
Uruchom skrypt kwerendy_portal.py. Przeanalizuj wynik wykonania skryptu i opisz schemat bazy danych.
Wynik działania skryptu:
Linia 1. CREATE TABLE sqlite podkreślnik sequence otwórz nawias okrągły name przecinek seq zamknij nawias okrągły.
Linia 2. CREATE TABLE panstwa otwórz nawias okrągły.
Linia 3. idp INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 4. nazwa VARCHAR otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły nazwa otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły.
Linia 5. zamknij nawias okrągły.
Linia 6. CREATE TABLE uzytkownicy otwórz nawias okrągły.
Linia 7. idu INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 8. imie VARCHAR otwórz nawias okrągły 20 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły imie otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły przecinek.
Linia 9. nazwisko VARCHAR otwórz nawias okrągły 30 zamknij nawias okrągły NOT NULL CHECK otwórz nawias okrągły nazwisko otwórz nawias ostrokątny zamknij nawias ostrokątny apostrof apostrof zamknij nawias okrągły przecinek.
Linia 10. idp INTEGER REFERENCES panstwa otwórz nawias okrągły idp zamknij nawias okrągły przecinek.
Linia 11. plec CHAR otwórz nawias okrągły 1 zamknij nawias okrągły DEFAULT apostrof apostrof.
Linia 12. zamknij nawias okrągły.
Linia 13. CREATE TABLE znajomosci otwórz nawias okrągły.
Linia 14. idu1 INTEGER NOT NULL REFERENCES uzytkownicy otwórz nawias okrągły idu zamknij nawias okrągły ON DELETE CASCADE przecinek.
Linia 15. idu2 INTEGER NOT NULL REFERENCES uzytkownicy otwórz nawias okrągły idu zamknij nawias okrągły ON DELETE CASCADE przecinek.
Linia 16. data DATE przecinek.
Linia 17. PRIMARY KEY otwórz nawias okrągły idu1 przecinek idu2 zamknij nawias okrągły.
Linia 18. zamknij nawias okrągły.
Linia 19. CREATE TABLE zdjecia otwórz nawias okrągły.
Linia 20. idz INTEGER PRIMARY KEY AUTOINCREMENT przecinek.
Linia 21. data DATE NOT NULL przecinek.
Linia 22. idu INTEGER REFERENCES uzytkownicy otwórz nawias okrągły idu zamknij nawias okrągły przecinek.
Linia 23. szer INTEGER DEFAULT 0 przecinek.
Linia 24. wys INTEGER DEFAULT 0.
Linia 25. zamknij nawias okrągły.
CREATE TABLE sqlite_sequence(name,seq)
CREATE TABLE panstwa (
idp INTEGER PRIMARY KEY AUTOINCREMENT,
nazwa VARCHAR(30) NOT NULL CHECK(nazwa <> '')
)
CREATE TABLE uzytkownicy (
idu INTEGER PRIMARY KEY AUTOINCREMENT,
imie VARCHAR(20) NOT NULL CHECK(imie <> ''),
nazwisko VARCHAR(30) NOT NULL CHECK(nazwisko <> ''),
idp INTEGER REFERENCES panstwa(idp),
plec CHAR(1) DEFAULT ''
)
CREATE TABLE znajomosci (
idu1 INTEGER NOT NULL REFERENCES uzytkownicy(idu) ON DELETE CASCADE,
idu2 INTEGER NOT NULL REFERENCES uzytkownicy(idu) ON DELETE CASCADE,
data DATE,
PRIMARY KEY(idu1, idu2)
)
CREATE TABLE zdjecia (
idz INTEGER PRIMARY KEY AUTOINCREMENT,
data DATE NOT NULL,
idu INTEGER REFERENCES uzytkownicy(idu),
szer INTEGER DEFAULT 0,
wys INTEGER DEFAULT 0
)
Baza składa się z czterech tabel.
W tabeli uzytkownicy występują pola:
idu – INTEGER, liczba całkowita, klucz główny, identyfikator użytkownika,
idp – INTEGER, liczba całkowita, klucz obcy, identyfikator państwa,
imie, nazwisko, plec – VARCHAR, CHAR, pola znakowe, płeć oznaczana jest jednym znakiem.
W tabeli panstwa występują pola:
idp – INTEGER, liczba całkowita, klucz główny, identyfikator państwa,
nazwa – VARCHAR, pole znakowe, nazwa państwa.
W tabeli znajomosci występują pola:
idu1, idu2 – INTEGER, liczby całkowite, klucze obce, które tworzą klucz główny,
szer, wys – INTEGER, liczby całkowite, szerokość i wysokość dodanego zdjęcia.
Tabele panstwa i uzytkownicy łączy relacja jeden‑do‑wielu. Tabele uzytkownicy i zdjecia łączy relacja jeden‑do‑wielu. Tabele uzytkownicy i znajomosci łączą dwie relacje jeden‑do‑wielu.
Zapytania grupujące i funkcje agregujące
Polecenie 2
Napisz zapytanie, które zwróci liczbę użytkowników zapisanych w bazie.
Rozwiązanie polecenia wymaga zliczenia rekordów z tabeli uzytkownicy. Użyjemy funkcji agregującejfunkcje agregującefunkcji agregującejCOUNT(), która zlicza rekordy pasujące do zapytania:
Linia 1. SELECT COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły AS liczba podkreślnik użytkowników.
Linia 2. FROM uzytkownicy średnik.
SELECT COUNT(*) AS liczba_użytkowników
FROM uzytkownicy;
Ważne!
W skrypcie kod SQL kolejnych kwerend dla uproszczenia możemy zapisywać w zmiennej kwerenda umieszczanej przed końcową funkcją wykonaj_zapytanie(kursor, kwerenda). Kolejne wystąpienia zmiennej będą nadpisywały poprzednie. Tym samym przy każdym uruchomieniu skryptu wykonywana będzie tylko jedna, ostatnia kwerenda. Dodatkowo możemy używać potrójnych cudzysłowów, aby umieszczać w skrypcie kwerendy zapisane dla czytelności w wielu liniach.
Kod po dodaniu zapytania odpowiedzi na bieżące pytanie będzie wyglądał następująco:
Linia 1. kwerenda znak równości cudzysłów SELECT name przecinek sql FROM sqlite podkreślnik master WHERE type znak równości apostrof table apostrof średnik cudzysłów.
Linia 2. kwerenda znak równości cudzysłów cudzysłów cudzysłów.
Linia 3. SELECT COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły AS liczba podkreślnik użytkowników.
Linia 4. FROM uzytkownicy średnik.
Linia 5. cudzysłów cudzysłów cudzysłów.
Linia 7. wykonaj podkreślnik zapytanie otwórz nawias okrągły kursor przecinek kwerenda zamknij nawias okrągły.
kwerenda = "SELECT name, sql FROM sqlite_master WHERE type='table';"
kwerenda = """
SELECT COUNT(*) AS liczba_użytkowników
FROM uzytkownicy;
"""
wykonaj_zapytanie(kursor, kwerenda)
Po wykonaniu kwerendy dowiemy się, że w bazie zapisano dane 84 użytkowników.
Polecenie 3
Napisz zapytanie, które zwróci nazwy państw oraz liczbę użytkowników z tych państw.
Odpowiedź wymaga pogrupowania użytkowników według identyfikatorów państw, a następnie zliczenia rekordów w poszczególnych grupach.
Linia 1. SELECT idp przecinek COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły AS liczba podkreślnik użytkowników.
Linia 2. FROM uzytkownicy.
Linia 3. GROUP BY idp średnik.
SELECT idp, COUNT(*) AS liczba_użytkowników
FROM uzytkownicy
GROUP BY idp;
W tym przykładzie widzimy, że grupowaniegrupowaniegrupowanie pozwala przeprowadzać obliczenia na polach rekordów wyodrębnionych według wartości kolumny podanej w klauzuli GROUP BY.
Wynik dotychczasowego zapytania nie jest czytelny, identyfikatory państw warto byłoby zastąpić nazwami. W tym celu dodamy do zapytania złączenie, które pozwoli pobrać nazwy państw z drugiej tabeli. Dodatkowo wyniki uporządkujemy malejąco według liczby użytkowników:
Linia 1. SELECT panstwa kropka nazwa przecinek COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły AS liczba podkreślnik użytkowników.
Linia 2. FROM uzytkownicy.
Linia 3. INNER JOIN panstwa ON uzytkownicy kropka idp znak równości panstwa kropka idp.
Linia 4. GROUP BY panstwa kropka nazwa.
Linia 5. ORDER BY liczba podkreślnik użytkowników DESC średnik.
SELECT panstwa.nazwa, COUNT(*) AS liczba_użytkowników
FROM uzytkownicy
INNER JOIN panstwa ON uzytkownicy.idp = panstwa.idp
GROUP BY panstwa.nazwa
ORDER BY liczba_użytkowników DESC;
Początkowe zwrócone rekordy:
Linia 1. Stany Zjednoczone 8.
Linia 2. Wielka Brytania 6.
Linia 3. Niemcy 5.
Linia 4. Polska 4.
Linia 5. Kanada 4.
Stany Zjednoczone 8
Wielka Brytania 6
Niemcy 5
Polska 4
Kanada 4
Polecenie 4
Napisz zapytanie zwracające nazwy państw, z których w bazie mamy po jednym użytkowniku.
Możemy zauważyć, że potrzebujemy zapytania podobnego do poprzedniego, ale z dodatkowym warunkiem. W którym miejscu należy go dodać? Może w klauzuli WHERE? To jednak błędne przypuszczenie, ponieważ warunki z klauzuli WHERE nakładane są na rekordy przed ich grupowaniem. Ponadto żeby wybrać państwa z jednym użytkownikiem, trzeba wcześniej tych użytkowników policzyć. Z tego wynika, że warunek musi zostać nałożony po zgrupowaniu i policzeniu rekordów. W takich przypadkach stosujemy klauzulę HAVING, w której możemy używać funkcji agregujących. Kwerenda przyjmie następującą postać:
Linia 1. SELECT panstwa kropka nazwa.
Linia 2. FROM panstwa przecinek uzytkownicy.
Linia 3. USING otwórz nawias okrągły idp zamknij nawias okrągły.
Linia 4. GROUP BY panstwa kropka nazwa.
Linia 5. HAVING COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły znak równości 1 średnik.
SELECT panstwa.nazwa
FROM panstwa, uzytkownicy
USING(idp)
GROUP BY panstwa.nazwa
HAVING COUNT(*) = 1;
W zapytaniu użyliśmy również klauzuli USING(), która może zastąpić klauzulę INNER JOIN ON, jeżeli pola tworzące złączenie mają taką samą nazwę w obu tabelach.
W systemach bazodanowych innych niż SQLite składnia klauzuli USING() wymaga klauzuli JOIN:
Linia 1. SELECT panstwa kropka nazwa.
Linia 2. FROM panstwa JOIN uzytkownicy.
Linia 3. USING otwórz nawias okrągły idp zamknij nawias okrągły.
Linia 4. GROUP BY panstwa kropka nazwa.
Linia 5. HAVING COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły znak równości 1 średnik.
SELECT panstwa.nazwa
FROM panstwa JOIN uzytkownicy
USING(idp)
GROUP BY panstwa.nazwa
HAVING COUNT(*) = 1;
Początkowe zwrócone rekordy:
Linia 1. Algieria.
Linia 2. Armenia.
Linia 3. Austria.
Linia 4. Chorwacja.
Linia 5. Dania.
Algieria
Armenia
Austria
Chorwacja
Dania
Polecenie 5
Napisz zapytanie zwracające imiona i nazwiska kobiet, które zrobiły najwięcej zdjęć.
Zacznijmy od pogrupowania rekordów z tabeli zdjęcia według identyfikatorów użytkowników i policzenia ich:
Linia 1. SELECT COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły FROM zdjecia GROUP BY idu cudzysłów średnik.
SELECT COUNT(*) FROM zdjecia GROUP BY idu";
Żeby wyeliminować z grupowania mężczyzn, musimy dołączyć tabelę uzytkownicy i dodać odpowiedni warunek, tym razem w klauzuli WHERE.
Linia 1. SELECT imie przecinek nazwisko przecinek COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły AS liczba podkreślnik zdjęć.
Linia 2. FROM zdjecia przecinek uzytkownicy.
Linia 3. USING otwórz nawias okrągły idu zamknij nawias okrągły.
Linia 4. WHERE plec znak równości apostrof K apostrof.
Linia 5. GROUP BY zdjecia kropka idu.
Linia 6. ORDER BY COUNT otwórz nawias okrągły asterysk zamknij nawias okrągły DESC średnik.
SELECT imie, nazwisko, COUNT(*) AS liczba_zdjęć
FROM zdjecia, uzytkownicy
USING(idu)
WHERE plec = 'K'
GROUP BY zdjecia.idu
ORDER BY COUNT(*) DESC;
Przeanalizujmy działanie zapytania: wszystkie rekordy z tabeli zdjecia złączone z odpowiednimi rekordami z tabeli uzytkownicy zostają wybrane, następnie odrzucane są te, które nie spełniają warunku z klauzuli WHERE, reszta jest grupowana według identyfikatora użytkownika z tabeli zdjecia i zliczana, na koniec zostają posortowane malejąco według liczby zdjęć.
Ćwiczenie 1
Załóżmy, że chcemy zobaczyć dane tylko pięciu użytkowników, którzy dodali do bazy najwięcej zdjęć. Wystarczy, że uzupełnimy zapytanie klauzulą LIMIT 5. Przetestuj to rozwiązanie.
Ważne!
Przed grupowaniem można pozbyć się rekordów, które nas nie interesują, za pomocą warunku w klauzuli WHERE.
Polecenie 6
Napisz zapytanie zwracające imiona, nazwiska i liczbę znajomości zawartych przez użytkowników portalu.
Rozwiązanie zadania zaczniemy od wyświetlenia imion i nazwisk osób, które zawarły znajomość. W tabeli znajomosci mamy niepowtarzające się pary identyfikatorów użytkowników: idu1 i idu2. Kwerenda, która pokaże te identyfikatory oraz imię i nazwisko pierwszego użytkownika, może wyglądać tak:
Linia 1. SELECT idu1 przecinek imie przecinek nazwisko przecinek idu2.
Linia 2. FROM uzytkownicy.
Linia 3. INNER JOIN znajomosci ON idu znak równości idu1 średnik.
SELECT idu1, imie, nazwisko, idu2
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu1;
Początkowe zwrócone rekordy:
Linia 1. 1 Joshua King 22.
Linia 2. 1 Joshua King 26.
Linia 3. 1 Joshua King 36.
Linia 4. 1 Joshua King 46.
Linia 5. 1 Joshua King 47.
Linia 6. 1 Joshua King 69.
Linia 7. 1 Joshua King 74.
1 Joshua King 22
1 Joshua King 26
1 Joshua King 36
1 Joshua King 46
1 Joshua King 47
1 Joshua King 69
1 Joshua King 74
Żeby wyświetlić imiona i nazwiska osób, których identyfikator zawarty jest w polu idu2, przekształcimy powyższą kwerendę w podzapytaniepodzapytaniepodzapytanie:
Linia 1. SELECT q1 kropka idu1 przecinek q1 kropka imie przecinek q1 kropka nazwisko przecinek q1 kropka idu2 przecinek u kropka imie przecinek u kropka nazwisko.
Linia 2. FROM otwórz nawias okrągły.
Linia 3. SELECT idu1 przecinek imie przecinek nazwisko przecinek idu2.
Linia 4. FROM uzytkownicy.
Linia 5. INNER JOIN znajomosci ON idu znak równości idu1.
Linia 6. zamknij nawias okrągły q1 przecinek uzytkownicy u.
Linia 7. WHERE u kropka idu znak równości q1 kropka idu2 średnik.
SELECT q1.idu1, q1.imie, q1.nazwisko, q1.idu2, u.imie, u.nazwisko
FROM (
SELECT idu1, imie, nazwisko, idu2
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu1
) q1, uzytkownicy u
WHERE u.idu =q1.idu2;
Początkowe zwrócone rekordy:
Linia 1. 1 Joshua King 22 Frank Dijkstra.
Linia 2. 1 Joshua King 26 Joshua Nelson.
Linia 3. 1 Joshua King 36 Milan Petrovic.
Linia 4. 1 Joshua King 46 Laura Mello.
Linia 5. 1 Joshua King 47 Mia Hoffmann.
Linia 6. 1 Joshua King 69 Grace Doherty.
Linia 7. 1 Joshua King 74 Luka Wagner.
Linia 8. kropka kropka kropka.
Linia 9. 22 Frank Dijkstra 2 Leonardo De Luca.
Linia 10. 22 Frank Dijkstra 8 Samuel Ramirez.
Linia 11. 22 Frank Dijkstra 36 Milan Petrovic.
Linia 12. 22 Frank Dijkstra 62 Filip Kralj.
Linia 13. 22 Frank Dijkstra 67 Artjoms Klavins.
Linia 14. 22 Frank Dijkstra 75 Elise Wouters.
1 Joshua King 22 Frank Dijkstra
1 Joshua King 26 Joshua Nelson
1 Joshua King 36 Milan Petrovic
1 Joshua King 46 Laura Mello
1 Joshua King 47 Mia Hoffmann
1 Joshua King 69 Grace Doherty
1 Joshua King 74 Luka Wagner
...
22 Frank Dijkstra 2 Leonardo De Luca
22 Frank Dijkstra 8 Samuel Ramirez
22 Frank Dijkstra 36 Milan Petrovic
22 Frank Dijkstra 62 Filip Kralj
22 Frank Dijkstra 67 Artjoms Klavins
22 Frank Dijkstra 75 Elise Wouters
Po przejrzeniu wszystkich wyników zauważymy, że aby zliczyć wszystkie znajomości nawiązane przez użytkowników, trzeba wziąć pod uwagę znajomości, które nawiązali oni, i znajomości, które nawiązano z nimi.
Tworzymy dwa zapytania. Pierwsze pokaże imię, nazwisko oraz liczbę znajomości, które zawarli użytkownicy – rekordy zostaną zgrupowane według pola idu1. Drugie pokaże imię, nazwisko oraz liczbę znajomości, które z użytkownikami zawarły inne osoby – rekordy zgrupujemy według pola idu2. W kwerendach wykorzystamy aliasy:
Linia 1. SELECT imie przecinek nazwisko przecinek COUNT otwórz nawias okrągły idu1 zamknij nawias okrągły AS z1.
Linia 2. FROM uzytkownicy.
Linia 3. INNER JOIN znajomosci ON idu znak równości idu1.
Linia 4. GROUP BY idu1 średnik.
SELECT imie, nazwisko, COUNT(idu1) AS z1
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu1
GROUP BY idu1;
Początkowe zwrócone rekordy:
Linia 1. Joshua King 7.
Linia 2. Leonardo De Luca 8.
Linia 3. Aleksandra Krawczyk 8.
Linia 4. Luka Schulte 2.
Linia 5. Jayden Harper 8.
Joshua King 7
Leonardo De Luca 8
Aleksandra Krawczyk 8
Luka Schulte 2
Jayden Harper 8
Linia 1. SELECT imie przecinek nazwisko przecinek COUNT otwórz nawias okrągły idu2 zamknij nawias okrągły AS z2.
Linia 2. FROM uzytkownicy.
Linia 3. INNER JOIN znajomosci ON idu znak równości idu2.
Linia 4. GROUP BY idu2 średnik.
SELECT imie, nazwisko, COUNT(idu2) AS z2
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu2
GROUP BY idu2;
Początkowe zwrócone rekordy:
Linia 1. Joshua King 7.
Linia 2. Leonardo De Luca 4.
Linia 3. Aleksandra Krawczyk 13.
Linia 4. Luka Schulte 5.
Linia 5. Jayden Harper 6.
Joshua King 7
Leonardo De Luca 4
Aleksandra Krawczyk 13
Luka Schulte 5
Jayden Harper 6
Jeżeli popatrzymy na wyniki powyższych kwerend, zauważymy na przykład to, że użytkownik Leonardo De Luca zawarł osiem znajomości, a z nim zawarto cztery znajomości. Więc aby pokazać, ile znajomości zawarł użytkownik, musimy dopasować rekordy z obydwu kwerend według nazwisk użytkowników i dodać do siebie pola aliasowane jako z1 oraz z2. W ten sposób przygotowane kwerendy wykorzystamy jako podzapytaniapodzapytaniepodzapytania.
Linia 1. SELECT q1 kropka imie przecinek q1 kropka nazwisko przecinek q1 kropka z1 plus q2 kropka z2 AS liczba podkreślnik znajomosci.
Linia 2. FROM otwórz nawias okrągły.
Linia 3. SELECT imie przecinek nazwisko przecinek COUNT otwórz nawias okrągły idu1 zamknij nawias okrągły AS z1.
Linia 4. FROM uzytkownicy.
Linia 5. INNER JOIN znajomosci ON idu znak równości idu1.
Linia 6. GROUP BY idu1.
Linia 7. zamknij nawias okrągły q1.
Linia 8. INNER JOIN otwórz nawias okrągły.
Linia 9. SELECT imie przecinek nazwisko przecinek COUNT otwórz nawias okrągły idu1 zamknij nawias okrągły AS z2.
Linia 10. FROM uzytkownicy.
Linia 11. INNER JOIN znajomosci ON idu znak równości idu2.
Linia 12. GROUP BY idu2.
Linia 13. zamknij nawias okrągły q2.
Linia 14. ON q1 kropka nazwisko znak równości q2 kropka nazwisko.
Linia 15. ORDER BY liczba podkreślnik znajomosci DESC średnik.
SELECT q1.imie, q1.nazwisko, q1.z1 + q2.z2 AS liczba_znajomosci
FROM (
SELECT imie, nazwisko, COUNT(idu1) AS z1
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu1
GROUP BY idu1
) q1
INNER JOIN (
SELECT imie, nazwisko, COUNT(idu1) AS z2
FROM uzytkownicy
INNER JOIN znajomosci ON idu=idu2
GROUP BY idu2
) q2
ON q1.nazwisko = q2.nazwisko
ORDER BY liczba_znajomosci DESC;
Na początku wykonana będzie pierwsza kwerenda po klauzuli FROM nazwana q1, następnie druga wstawiona po klauzuli INNER JOIN nazwana q2. Rekordy obydwu kwerend zostaną połączone na podstawie identycznych nazwisk. Wtedy z kwerendy q1 wybrane zostaną pola imie i nazwisko, a następnie przeprowadzone będzie sumowanie pól z1 i z2, przez co otrzymamy pole wyliczeniowepole wyliczeniowepole wyliczeniowe nazwane liczba_znajomosci. Wyniki zostaną uporządkowane malejąco według liczby znajomości.
Początkowe zwrócone rekordy:
Linia 1. Aleksandra Krawczyk 21.
Linia 2. Grace Doherty 21.
Linia 3. Filip Kralj 20.
Linia 4. Lautero Quiroga 18.
Linia 5. Andreas Jakobsson 18.
Aleksandra Krawczyk 21
Grace Doherty 21
Filip Kralj 20
Lautero Quiroga 18
Andreas Jakobsson 18
Słownik
funkcje agregujące
funkcje agregujące
funkcje umożliwiające wykonywanie obliczeń na grupach rekordów, jak również wyszukiwanie i zliczanie rekordów spełniających określone warunki
grupowanie
grupowanie
tworzenie zbiorów rekordów na podstawie takich samych wartości z podanej kolumny; grupowanie zazwyczaj poprzedza zastosowanie funkcji agregującej, która przeprowadza obliczenia na grupie rekordów
podzapytanie
podzapytanie
zapytanie SELECT umieszczone wewnątrz innego zapytania SELECT, podzapytanie wykonywane w pierwszej kolejności, a jego wyniki są źródłem dla zewnętrznego zapytania
pole wyliczeniowe
pole wyliczeniowe
pole w zapytaniu, którego wartość obliczana jest dynamicznie z wykorzystaniem danych pobieranych z bazy