Wróć do: Bazy danych
zaawansowany SQLdatyDateDiffmatura rozszerzona z informatyki

Funkcje daty

Praca z datami w SQL – data bieżąca, różnica dat, wyciąganie roku i miesiąca oraz zapis daty w warunku.

01

Opis

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.

02

Funkcje

Date()
dzisiejsza dataBez godziny. Wywoływana bez argumentów.
Now()
data i godzinaJak wyżej, ale z czasem – uwaga przy odejmowaniu.
Year(data)
rok z datyZwraca liczbę czterocyfrową.
Month(data)
miesiąc z datyLiczba od 1 do 12.
Day(data)
dzień miesiącaLiczba od 1 do 31.
DateDiff("jednostka"; od; do)
różnica w zadanej jednostceJednostka jako tekst: "yyyy" rok, "m" miesiąc, "d" dzień, "q" kwartał.
DatePart("jednostka"; data)
część datyUniwersalna alternatywa dla Year i Month, przydatna dla kwartałów.
03

Dialekt

W AccessieStandardowy SQLZnaczenie
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
04

Zapytanie

-- Data wpisana wprost: w Accessie w znakach # i w formacie amerykańskim
SELECT nazwisko, data_ur
FROM uczniowie
WHERE data_ur > #1/1/2007#
Wynik zapytania
nazwiskodata_ur
Kowalska2007-03-12
Wiśniewski2007-01-28
Dąbrowski2007-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)
Wynik zapytania
rocznikilu
20062
20073
-- 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

Na maturze

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.

06

Najczęściej zadawane pytania

Dlaczego różnica dat daje dziwnie dużą liczbę?

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.

Czy da się sortować po dacie?

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'.

Jak wybrać wszystkie zdarzenia z jednego miesiąca?

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.

Powiązane zagadnienia