Podstawy baz danych. Laboratorium nr 4.

Baza danych:

Podczas tych i kolejnych zajęć korzystać będziemy z przykładowej bazy danych "Sakila" dostępnej na serwerze uczelnianym torus.uck.pk.edu.pl. Adres, nazwy urzytkowników, hasła oraz sposób połącznia z wykorzystaniem MySQL Workbench tak jak poprzednio z tą różnicą że łączymy się z bazą o nazwie sakila_DBii gdzie ii to numer użytkownika. Jakiekolwiek problemy z logowaniem proszę zgłaszać na zajęciach lub poprzez kontakt mailowy.

In [1]:
# kod pythona do połączenia z bazą i wykonywania zapytań sql w jupyter
from sqlalchemy import create_engine
engine = create_engine('mysql+pymysql://root:*****@127.0.0.1:3306/sakila')
%load_ext sql_magic
%config SQL.conn_name = 'engine'

Funkcje agregujące

Są to funkcje umożliwiające wykonanie pożądanych operacji na całych tabelach lub tylko niektórych zbiorach danych, zwracające ogólne wyniki dotyczące np. liczebności czy średnich wartości.

COUNT()

Zwraca liczbę niepustych wartości.

Przykład:

Liczba rekorów w tabeli film

In [2]:
%%read_sql
SELECT COUNT(*) FROM film
Query started at 12:59:00 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[2]:
COUNT(*)
0 1000

Liczba niepustych wartości w kolumnie title

In [3]:
%%read_sql
SELECT COUNT(title) FROM film
Query started at 12:59:02 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[3]:
COUNT(title)
0 1000

Liczba unikalnych wartości w kolumnie rating

In [4]:
%%read_sql
SELECT COUNT( DISTINCT rating) FROM film
Query started at 12:59:05 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[4]:
COUNT( DISTINCT rating)
0 5

AVG(), MAX(), MIN(), SUM(), STDDEV()

Funkcje zwracające odpowiednio wartość średnią, maksimum, minimum, sumę oraz odchylenie standardowe z podanej kolumny.

Przykład:

Wartość średnia, maksimum, minimum, suma oraz odchylenie standardowe długości filmów w tabeli film

In [5]:
%%read_sql
SELECT AVG(length), MAX(length), MIN(length), SUM(length), STDDEV(length) FROM film
Query started at 12:59:07 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[5]:
AVG(length) MAX(length) MIN(length) SUM(length) STDDEV(length)
0 115.272 185 46 115272.0 40.406114

Oczywiście możliwe jest dołożenie do zapytania warunku klauzuli WHERE

In [6]:
%%read_sql
SELECT AVG(length), MAX(length), MIN(length), SUM(length), STDDEV(length) FROM film
WHERE rating = 'G'
Query started at 12:59:10 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[6]:
AVG(length) MAX(length) MIN(length) SUM(length) STDDEV(length)
0 111.0506 185 47 19767.0 41.654312

Aliasing

Jak widać na powyższych przykładach generowane automatycznie nazwy kolumn nie zawsze są przyjemne. Dlatego możemy nadać im własne nazwy za pomocą słowa kluczowego AS.

Przykład:

Wartość średnia, maksimum, minimum, suma oraz odchylenie standardowe długości filmów w tabeli film. Kolumny nazwane odpowiednio srednia, maksimum, minimum, suma, std.

In [7]:
%%read_sql
SELECT AVG(length) AS srednia, MAX(length) AS maksimum, MIN(length) AS minimum, SUM(length) AS suma, STDDEV(length) AS std
FROM film
Query started at 12:59:12 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[7]:
srednia maksimum minimum suma std
0 115.272 185 46 115272.0 40.406114

Arytmetyka

W SQL'u możliwe jest też wykonywania działań arytmetycznych na kolumnach takich jak +, -, *, /.

Przykłady:

Długość filmów w godzinach

In [8]:
%%read_sql
SELECT length AS dl_minuty, (length/60.0) AS dl_godziny FROM film
LIMIT 6
Query started at 12:59:15 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[8]:
dl_minuty dl_godziny
0 86 1.4333
1 48 0.8000
2 50 0.8333
3 117 1.9500
4 130 2.1667
5 169 2.8167

Przykładowa operacja na dwóch kolumnach

In [9]:
%%read_sql
SELECT length, length*rental_rate AS 'len*ren' FROM film
LIMIT 6
Query started at 12:59:18 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[9]:
length len*ren
0 86 85.14
1 48 239.52
2 50 149.50
3 117 349.83
4 130 388.70
5 169 505.31

ORDER BY

Sortownie wyniku zapytania w mysql odbywa się poprzez użycie klauzuli ORDER BY. Sortować możemy rosnąco ASC lub malejąco DESC. Domyślnie sortujemy rosnąco.

Przykłady:

Tytułu filmów w porządku 'Z-A'. Pierwsze 10 rekordów.

In [10]:
%%read_sql
SELECT title FROM film
ORDER BY title DESC
LIMIT 10
Query started at 12:59:21 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[10]:
title
0 ZORRO ARK
1 ZOOLANDER FICTION
2 ZHIVAGO CORE
3 YOUTH KICK
4 YOUNG LANGUAGE
5 YENTL IDAHO
6 WYOMING STORM
7 WRONG BEHAVIOR
8 WRATH MILE
9 WORST BANGER

Sortowanie po kilku kolumnach, np. według rental_duration rosnąco, następnie według długości malejąco. Pierwsze 10 rekordów.

In [11]:
%%read_sql
SELECT title, rental_duration, length FROM film
ORDER BY rental_duration, length DESC
LIMIT 10
Query started at 12:59:24 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[11]:
title rental_duration length
0 SWEET BROTHERHOOD 3 185
1 SONS INTERVIEW 3 184
2 KING EVOLUTION 3 184
3 WIFE TURN 3 183
4 BAKED CLEOPATRA 3 182
5 SEARCHERS WAIT 3 182
6 REDEMPTION COMFORTS 3 179
7 CASUALTIES ENCINO 3 179
8 KICK SAVANNAH 3 179
9 CAUSE DATE 3 179

GROUP BY

Kluzula GROUP BY umożliwia wykonywanie funkcji grupujących na grupie wartości wyodrębnionych na podstawie wartości innej kolumny. Aby użyć kolumny do grupowania, musimy pamiętać, aby umieścić ją w liście kolumn, zaraz po słowie SELECT. W przeciwnym razie nie będzie ona dostępna dla klauzuli grupującej GROUP BY.

Przykłady:

Średnia długość filmów o tym samym ratingu.

In [12]:
%%read_sql
SELECT rating, AVG(length) AS srednia FROM film
GROUP BY rating
Query started at 12:59:27 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[12]:
rating srednia
0 G 111.0506
1 PG 112.0052
2 PG-13 120.4439
3 R 118.6615
4 NC-17 113.2286

Grupować można również po kilku kolumnach, np. najpierw po rental_duration a później każdą z tych grup po rating. Możemy również takie grupy sortować.

In [13]:
%%read_sql
SELECT rental_duration, rating, AVG(length) AS srednia FROM film
GROUP BY rental_duration, rating
ORDER BY rental_duration DESC
Query started at 12:59:30 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[13]:
rental_duration rating srednia
0 7 G 116.3448
1 7 PG 111.9556
2 7 PG-13 118.2727
3 7 R 131.2727
4 7 NC-17 118.7000
5 6 G 128.0000
6 6 PG 104.8205
7 6 PG-13 118.5200
8 6 R 127.1852
9 6 NC-17 111.7895
10 5 G 109.5758
11 5 PG 127.4242
12 5 PG-13 119.6429
13 5 R 122.1000
14 5 NC-17 105.4186
15 4 G 102.2857
16 4 PG 103.8293
17 4 PG-13 120.0000
18 4 R 108.8113
19 4 NC-17 119.1515
20 3 G 100.4286
21 3 PG 115.0278
22 3 PG-13 126.7692
23 3 R 112.4286
24 3 NC-17 113.3243

HAVING

Klauzula HAVING, znajdująca się zaraz po GROUP BY, służy do określania dodatkowych kryteriów przy grupowaniu (jest to odpowiednik warunku WHERE w zapytaniach bez funkcji grupujących).

Przykład:

Średnia długość filmów o tym samym rental_duration, ale tylko tych gdzie średnia długość jest większa od 115 minut

In [14]:
%%read_sql
SELECT rental_duration, AVG(length) AS srednia FROM film
GROUP BY rental_duration
HAVING AVG(length) > 115
Query started at 12:59:33 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[14]:
rental_duration srednia
0 5 116.5602
1 6 117.0377
2 7 118.8272

CASE WHEN THEN ELSE END

Tworzenie kolumn, które przyjmują wartości w zależności od spełnionych warunków.

Przykład:

Chcemy podzielić filmy na trzy kategorie, krótki, średni i długi. W tym celu najpierw stworzymy nową kolumnę w której będą własnie takie wartości w zależności od długości filmu.

In [15]:
%%read_sql
SELECT length,
CASE WHEN length > 120
    THEN 'dlugi'
    WHEN length > 60
    THEN 'sredni'
    ELSE 'krotki' END
    AS etykieta
FROM film
LIMIT 10
Query started at 12:59:36 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[15]:
length etykieta
0 86 sredni
1 48 krotki
2 50 krotki
3 117 sredni
4 130 dlugi
5 169 dlugi
6 62 sredni
7 54 krotki
8 114 sredni
9 63 sredni

Teraz możemy rozszeżyć zapytanie o grupowanie danych względem utworzonej etykiety i policzyć np. ilość filmów w danej grupie

In [16]:
%%read_sql
SELECT COUNT(*) AS ilosc,
CASE WHEN length > 120
    THEN 'dlugi'
    WHEN length > 60
    THEN 'sredni'
    ELSE 'krotki' END
    AS etykieta
FROM film
GROUP BY etykieta
ORDER BY ilosc
Query started at 12:59:45 PM ?rodkowoeuropejski czas stand.; Query executed in 0.00 m
Out[16]:
ilosc etykieta
0 104 krotki
1 439 sredni
2 457 dlugi