SQL uczniowie zwykle lubią, bo wynik widać od razu — o ile kolejność tematów nie przeskakuje fundamentów. JOIN bez kluczy jest czarną magią, GROUP BY bez funkcji agregujących — jeszcze większą, a podzapytania przed JOIN wprowadzają zamęt. Poniżej plan 15 lekcji z zależnościami oraz program, który układa je w poprawnej kolejności, liczy czas i sprawdza własny układ nauczyciela.
Materiał jest przeznaczony dla nauczyciela. Założenia: lekcja trwa jedną godzinę lekcyjną (projekt — dwie), nauka odbywa się dwie godziny tygodniowo, a zależności są propozycją. Lekcje to opublikowane na blogu materiały z zadaniami; SQL w nich sprawdzono w SQLite, a różnice składni w MySQL/MariaDB trzeba sprawdzić na używanym serwerze.
Przygotowanie stanowisk
Potrzebny jest Python 3 i edytor lub IDLE. Rozpakuj pakiet z sekcji materiałów do osobnego folderu i uruchamiaj skrypty z tego folderu. Program uruchomisz przez Run → Run Module albo poleceniem python start.py, python3 start.py lub py start.py.
Cele i plan lekcji
Po zajęciach uczeń potrafi:
- ułożyć dział SQL w kolejności uwzględniającej zależności;
- policzyć liczbę godzin i tygodni;
- sprawdzić własny układ lekcji pod kątem zależności;
- wskazać, które lekcje zależą od wybranego tematu (np.
GROUP BY).
| Czas | Praca na lekcji |
|---|---|
| 0–10 min | Zależności między tematami |
| 10–25 min | Wyznaczenie kolejności w programie |
| 25–40 min | Kontrola własnego układu |
| 40–45 min | Wnioski i planowanie ocen |
Plan 15 lekcji
Razem 16 godzin, czyli 8 tygodni przy dwóch godzinach tygodniowo (bez godzin na powtórki).
Zasady kolejności
- Najpierw odczyt (
SELECT,WHERE, sortowanie), potem agregacje iGROUP BY. - Klucze przed
JOIN: uczeń musi rozumieć, co łączy tabele. - Modyfikacja danych (
INSERT,UPDATE,DELETE) poWHERE— żeby wiedzieć, że warunek decyduje, co zostanie zmienione. - Projektowanie tabel i normalizacja dopiero po kluczach.
- Podzapytania na końcu, gdy znane są
JOINiGROUP BY.
Co robi program
Funkcja kolejnosc wybiera w każdym kroku lekcję, której zależności są już zrealizowane; naruszenia wykrywa lekcje stojące przed swoimi zależnościami. Po zamianie WHERE z lekcją o funkcjach agregujących program wskazuje, które lekcje trafiły przed swoje zależności.
Sprawdziany
Po pierwszej części (odczyt i agregacje) warto zaplanować krótką kartkówkę, a na koniec — sprawdzian (Sprawdzian SQL — zapytania do bazy z kluczem i punktacją).
Zadania
Zadanie 1. Kolejność. Wyznacz poprawną kolejność lekcji i policz lekcje, godziny i tygodnie przy 2 godz./tydz.
Zadanie 2. Własny układ. Zamień miejscami „WHERE” i „COUNT SUM AVG” i sprawdź, jakie zależności zostały naruszone.
Zadanie 3. Zależności. Wypisz lekcje zależne od „GROUP BY” i sprawdź, że zależność pierwszej lekcji od projektu tworzy cykl.
Dla chętnych: ułóż plan skrócony do 10 godzin dla klasy z krótszym wymiarem godzin.
Rozwiązanie i wyniki
# Plan dzialu: lekcja -> (godziny, lekcje, ktore musza byc wczesniej)
PLAN = {
"Relacyjne bazy": (1, []),
"SELECT": (1, ["Relacyjne bazy"]),
"WHERE": (1, ["SELECT"]),
"ORDER BY i LIMIT": (1, ["SELECT"]),
"LIKE IN BETWEEN": (1, ["WHERE"]),
"COUNT SUM AVG": (1, ["WHERE"]),
"GROUP BY": (1, ["COUNT SUM AVG"]),
"Klucze": (1, ["Relacyjne bazy"]),
"JOIN": (1, ["Klucze", "SELECT"]),
"INSERT UPDATE DELETE": (1, ["WHERE"]),
"Projektowanie tabel": (1, ["Klucze"]),
"Normalizacja": (1, ["Projektowanie tabel"]),
"Podzapytania": (1, ["JOIN", "GROUP BY"]),
"Sprawdzian SQL": (1, ["GROUP BY", "JOIN"]),
"Projekt sklepu": (2, ["JOIN", "GROUP BY", "Normalizacja", "INSERT UPDATE DELETE"]),
}
def kolejnosc(plan):
"""Jedna z poprawnych kolejnosci (sortowanie topologiczne); None, gdy zaleznosci tworza cykl."""
zrobione, wynik = set(), []
while len(wynik) < len(plan):
gotowe = [l for l in plan if l not in zrobione and all(w in zrobione for w in plan[l][1])]
if not gotowe:
return None
zrobione.add(gotowe[0])
wynik.append(gotowe[0])
return wynik
def naruszenia(plan, propozycja):
pozycje = {l: i for i, l in enumerate(propozycja)}
return [l + " przed " + w for l, (_, wymagane) in plan.items() for w in wymagane if pozycje[w] > pozycje[l]]
# Zadanie 1: kolejnosc i czas
proponowana = kolejnosc(PLAN)
print("Kolejnosc:", " > ".join(proponowana))
godziny = sum(h for h, _ in PLAN.values())
print("Lekcji:", len(PLAN), "| godzin:", godziny, "| tygodni przy 2 godz./tydz.:", -(-godziny // 2))
# Zadanie 2: kontrola wlasnego ukladu (zamiana dwoch lekcji miejscami)
wlasny = list(proponowana)
i, j = wlasny.index("WHERE"), wlasny.index("COUNT SUM AVG")
wlasny[i], wlasny[j] = wlasny[j], wlasny[i]
print("Wlasny uklad ma naruszenia:", naruszenia(PLAN, wlasny))
# Zadanie 3: zaleznosci i cykl
zalezne = [l for l, (_, w) in PLAN.items() if "GROUP BY" in w]
print("Zalezne od GROUP BY:", zalezne)
print("Cykl w planie:", kolejnosc(dict(PLAN, **{"Relacyjne bazy": (1, ["Projekt sklepu"])})) is None)
Program wypisze:
Kolejnosc: Relacyjne bazy > SELECT > WHERE > ORDER BY i LIMIT > LIKE IN BETWEEN > COUNT SUM AVG > GROUP BY > Klucze > JOIN > INSERT UPDATE DELETE > Projektowanie tabel > Normalizacja > Podzapytania > Sprawdzian SQL > Projekt sklepu
Lekcji: 15 | godzin: 16 | tygodni przy 2 godz./tydz.: 8
Wlasny uklad ma naruszenia: ['LIKE IN BETWEEN przed WHERE', 'COUNT SUM AVG przed WHERE']
Zalezne od GROUP BY: ['Podzapytania', 'Sprawdzian SQL', 'Projekt sklepu']
Cykl w planie: True
Plan ma 15 lekcji i 16 godzin, czyli 8 tygodni. Zamiana „WHERE” i „COUNT SUM AVG” narusza kilka zależności naraz (funkcje agregujące stoją przed lekcją, od której zależą, a lekcje zależne od WHERE — między innymi LIKE — są przed nią); dokładną listę wypisuje program. Od „GROUP BY” zależą „Podzapytania”, „Sprawdzian SQL” i „Projekt sklepu”.
Plik rozszerzenie.py (zadanie dla chętnych) wypisze:
8 8.0
Typowe błędy
| Objaw | Co sprawdzić |
|---|---|
JOIN bez kluczy | Uczeń nie rozumie, co łączy tabele. |
GROUP BY bez agregatów | Grupowanie ma sens z funkcjami COUNT, SUM, AVG. |
UPDATE przed WHERE | Łatwo zmienić wszystkie wiersze. |
| Podzapytania za wcześnie | Uczeń nie zna jeszcze łączenia i grupowania. |
| Normalizacja przed kluczami | Brak podstaw do rozumienia zależności między tabelami. |
| Brak kartkówki przed projektem | Trudno ocenić, kto potrzebuje powtórki. |
Pytania kontrolne i punktacja
- Dlaczego klucze są przed JOIN?
- Co zależy od lekcji o GROUP BY?
- Dlaczego INSERT, UPDATE i DELETE planujemy po WHERE?
Odpowiedzi: Bo JOIN łączy tabele przez klucze, więc uczeń musi rozumieć, czym one są. Podzapytania, sprawdzian i projekt. Aby uczeń wiedział, że warunek decyduje, które wiersze zostaną zmienione lub usunięte.
Proponowana punktacja (razem 10 punktów): zadanie 1 — kolejność i liczby 3 pkt; zadanie 2 — kontrola układu 3 pkt; zadanie 3 — zależności i cykl 2 pkt; planowanie w pytaniach 2 pkt. Zadanie dla chętnych nie jest wymagane do pełnej oceny.
Materiały do pobrania
Rozpakuj ZIP przed otwarciem plików. Materiały są dostępne bez logowania; publiczne rozwiązanie służy nauce i samodzielnemu sprawdzeniu, a nie poufnemu sprawdzianowi.
Co dalej?
Następny krok to dobór sprawdzianów, zadań powtórkowych i projektów w dziale SQL. Ten materiał rozwija dział o planowaniu nauczania baz danych w kursie SQL w TablicaPro, gdzie znajdziesz prezentacje, ćwiczenia i testy do prowadzenia lekcji.
Źródła techniczne: sortowanie topologiczne w Wikipedii oraz dokumentacja SQLite. Zobacz też lekcję o planowaniu działu HTML i CSS.
Poprowadź kolejne lekcje SQL
Pełny kurs: prezentacje, ćwiczenia i testy do pracy z klasą.
Kup dostęp do kursu SQL →