Praca z datami w SQL – data bieżąca, różnica dat, wyciąganie roku i miesiąca oraz zapis daty w warunku.
Data w bazie nie jest tekstem. Wygląda jak tekst na ekranie, ale przechowywana jest jako liczba – co ma jedną bardzo praktyczną konsekwencję: daty można od siebie odejmować, a wynikiem jest liczba dni między nimi. Na tej jednej właściwości opiera się większość zadań z datami.
Z tego samego powodu daty da się porównywać zwykłymi operatorami: data późniejsza jest „większa" od wcześniejszej. Warunek „wizyty po 16 maja" to po prostu > z odpowiednią datą po prawej stronie.
Zapis daty w warunku to najczęstsze źródło kłopotów. Nie wystarczy napisać jej w apostrofach jak tekst – trzeba powiedzieć bazie, że to data. Access wymaga otoczenia jej znakami # i zapisu w formacie amerykańskim (miesiąc, dzień, rok), niezależnie od ustawień systemu. Alternatywnie można użyć funkcji, która zamienia datę zapisaną po polsku na wewnętrzny format bazy – to zapis bezpieczniejszy, bo nie wymaga pamiętania o kolejności.
Data bieżąca jest dostępna jako funkcja, którą wywołuje się bez argumentów. Warto rozróżnić funkcję zwracającą samą datę od tej, która zwraca datę razem z godziną – przy odejmowaniu różnica potrafi zmienić wynik o jeden dzień.
Różnica dat w wybranej jednostce. Odejmowanie daje wynik w dniach. Gdy potrzebujesz lat, miesięcy czy kwartałów, służy do tego osobna funkcja, której pierwszym parametrem jest jednostka. Uwaga: liczy ona przekroczone granice jednostki, a nie pełne okresy – różnica lat między 31 grudnia a 1 stycznia wyniesie 1, mimo że minął jeden dzień.
Stąd bierze się klasyczna pułapka z liczeniem wieku. Odjęcie samych roczników daje wynik zawyżony dla wszystkich, którzy w tym roku jeszcze nie mieli urodzin. Dokładniejszy sposób to policzyć różnicę w dniach i podzielić przez średnią długość roku, a wynik obciąć do liczby całkowitej.
Wyciąganie części daty. Osobne funkcje zwracają z daty sam rok, sam miesiąc albo sam dzień. To wygodniejsze niż wycinanie fragmentów tekstu i działa niezależnie od formatu wyświetlania. Po tak wyciągniętej wartości można też grupować – na przykład zliczyć zdarzenia w poszczególnych latach.
Date()
Now()
Year(data)
Month(data)
Day(data)
DateDiff("jednostka"; od; do)
DatePart("jednostka"; data)
| W Accessie | Standardowy SQL | Znaczenie |
|---|---|---|
Date() |
CURRENT_DATE |
dzisiejsza data |
#5/16/2024# |
DATE '2024-05-16' |
data wpisana wprost w warunku |
DateDiff("d"; a; b) |
(b - a) |
różnica w dniach |
Year(data) |
EXTRACT(YEAR FROM data) |
rok z daty |
-- Data wpisana wprost: w Accessie w znakach # i w formacie amerykańskim SELECT nazwisko, data_ur FROM uczniowie WHERE data_ur > #1/1/2007#
| nazwisko | data_ur |
|---|---|
| Kowalska | 2007-03-12 |
| Wiśniewski | 2007-01-28 |
| Dąbrowski | 2007-08-30 |
-- Grupowanie po roku wyciągniętym z daty SELECT Year(data_ur) AS rocznik, COUNT(*) AS ilu FROM uczniowie GROUP BY Year(data_ur)
| rocznik | ilu |
|---|---|
| 2006 | 2 |
| 2007 | 3 |
-- Wiek liczony w dniach i dzielony przez długość roku - dokładniejszy niż -- różnica roczników. Wyniku nie pokazujemy: zależy od dnia uruchomienia. SELECT nazwisko, Int(DateDiff("d"; data_ur; Date()) / 365.25) AS wiek FROM uczniowie ORDER BY wiek DESC
Nie licz wieku odejmowaniem roczników. Różnica lat kalendarzowych zawyża wiek każdemu, kto w tym roku jeszcze nie obchodził urodzin – czyli średnio połowie osób w tabeli. Jeśli zadanie prosi o wiek, bezpieczniejsza jest droga przez różnicę w dniach.
Sprawdź, jak Twoje narzędzie chce zapisaną datę. To najczęstsza przyczyna zapytania, które „nie działa bez powodu". Znaki # i format amerykański w Accessie łatwo pomylić z zapisem tekstowym w apostrofach.
Uważaj na godzinę. Jeśli kolumna przechowuje datę razem z czasem, porównanie = #16.05.2024# nie znajdzie zdarzeń z tego dnia zapisanych o 14:30 – bo to inna wartość. W takim wypadku pewniejszy jest warunek na przedziale albo porównywanie samych wyciągniętych części daty.
Wynik dzielenia rzadko wychodzi okrągły, więc przy liczeniu wieku pamiętaj o obcięciu części ułamkowej – szczegóły przy wyrażeniach.
Bo wynik jest w dniach. 6500 to nie błąd, tylko mniej więcej osiemnaście lat. Jeśli potrzebujesz innej jednostki, użyj funkcji liczącej różnicę z podaną jednostką zamiast zwykłego odejmowania.
Tak, i to poprawnie chronologicznie – bo data jest liczbą, a nie tekstem. To jedna z przewag trzymania dat w kolumnie typu data zamiast w tekście: tekst '01.12.2024' posortowałby się przed '02.01.2024'.
Najczytelniej przez warunek na przedziale dat – od pierwszego dnia miesiąca do ostatniego – albo przez porównanie wyciągniętego roku i miesiąca. Drugie podejście bywa wolniejsze na dużych tabelach, ale na maturze jest zupełnie wystarczające.
Zagadnienia z tego samego obszaru matury – warto je powtórzyć razem: