SQL od podstaw · część 15

Funkcje skalarne liczbowe

Obliczenia, rabaty, zaokrąglanie i dzielenie. Zrozum, kiedy typ liczby zmienia wynik oraz czym różnią się popularne silniki.

Część bazodanowa INF.03

Liczba w wyniku może być obliczeniem

SQL potrafi obliczyć cenę po rabacie, wartość pozycji lub różnicę między pomiarami. Operatory +, -, * i / łączą wartości; nawiasy jawnie ustalają kolejność. Funkcje liczbowe, podobnie jak tekstowe, działają dla wyrażeń w poszczególnych wierszach. SUM wartości wielu wierszy poznamy oddzielnie.

SELECT nazwa, cena,
       ROUND(cena * 0.90, 2) AS po_rabacie
FROM produkty ORDER BY id;

Rabat 10% pozostawia 90% ceny. Oczekiwane kwoty: Klawiatura 108, Mysz 54, Monitor 720, Kabel 22.5. To wartości liczbowe; format „22,50 zł” należy do prezentacji. ROUND nie gwarantuje wyświetlenia dwóch cyfr po przecinku.

ABS, ROUND, FLOOR i CEILING

ABS(x)

Wartość bezwzględna: ABS(-7) = 7. Przydaje się do wielkości różnicy bez jej kierunku.

ROUND(x, n)

Zaokrąglenie do n miejsc po separatorze dziesiętnym. Reguły remisu i typ argumentu trzeba sprawdzić w silniku.

FLOOR(x)

Największa liczba całkowita nie większa od x: FLOOR(-2.3) = -3. To nie zwykłe odcięcie części ułamkowej.

CEILING / CEIL

Najmniejsza liczba całkowita nie mniejsza od x: CEILING(2.3) = 3. Oracle używa CEIL.

CelMySQL / MariaDBSQL ServerOracle 19cAccess
Wartość bezwzględnaABS(x)ABS(x)ABS(x)Abs(x)
ZaokrąglenieROUND(x, 2)ROUND(x, 2)ROUND(x, 2)Round(x, 2)
W dółFLOOR(x)FLOOR(x)FLOOR(x)Int(x)
W góręCEILING(x)CEILING(x)CEIL(x)-Int(-x)
Reszta z dzieleniaMOD(a,b) lub %a % bMOD(a,b)a Mod b

Dla dodatnich całkowitych 17 i 5 reszta wynosi 2. Reguły znaków, konwersji ułamków i dzielenia przez zero różnią się; nie traktuj tej tabeli jako translacji dowolnego wyrażenia. Access Fix(-2.3) daje -2, a Int(-2.3) daje -3.

5 / 2: typy zmieniają wynik

-- MySQL / MariaDB
SELECT 5 / 2 AS ulamek, 5 DIV 2 AS calkowite;
-- SQL Server
SELECT 5 / 2 AS calkowite,
       CAST(5 AS decimal(10,2)) / 2 AS ulamek;
-- Oracle 19c
SELECT 5 / 2 AS ulamek FROM dual;
-- Access: / jest dzieleniem zwykłym, \ całkowitym
SELECT 5 / 2 AS ulamek, 5 \ 2 AS calkowite;
-- SQLite
SELECT 5 / 2 AS calkowite, 5.0 / 2 AS ulamek;

MySQL / i Oracle NUMBER dają 2.5. SQL Server przy dwóch int daje 2, a SQLite przy dwóch integer także 2. W SQLite 5.0 zmienia operację na rzeczywistą. Rzutowanie dopiero gotowego wyniku 5/2 na liczbę ułamkową nie przywróci utraconej części.

W Edytorze SQL wybierz SQLite do obliczeń natywnych. Możesz użyć ABS i ROUND oraz podstawowej arytmetyki. FLOOR/CEILING, DIV i Mod Access są poza obecnym zakresem edytora. Tryb MySQL stosuje ograniczone mapowanie dzielenia na liczbę rzeczywistą, a tryb SQL Server odrzuca dzielenie, aby nie zgadywać typów. Pełną precyzję DECIMAL sprawdzaj w prawdziwej bazie; nasza cena ma w SQLite typ REAL.

Wypróbuj zapytanie

SQLite — rzeczywisty silnik przeglądarki. MySQL / SQL Server — ograniczona emulacja składni. Wybierz tryb SQLite do natywnego LIKE. Pozostałe tryby nie są rzeczywistymi serwerami. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.

Ładowanie edytora…

Zaokrąglenie jest regułą, nie dekoracją

SQL Server ROUND rozstrzyga połówki w kierunku od zera. MySQL dla dokładnych wartości stosuje podobną regułę, ale argumenty przybliżone mogą dawać wyniki zależne od użytej reprezentacji i biblioteki. Oracle NUMBER i liczby zmiennoprzecinkowe również nie są zamienne w każdym przypadku. Access/VBA Round stosuje zaokrąglanie do parzystej przy remisie: 2.5 do 2, 3.5 do 4. Nie emulujemy tej reguły Access przez SQLite ROUND.

Typ REAL/FLOAT przechowuje przybliżenie wielu ułamków dziesiętnych. Dla rozliczeń dobierz dokładny DECIMAL/NUMERIC (lub właściwy typ walutowy) i określ moment zaokrąglenia. Suma zaokrąglonych pozycji może różnić się od zaokrąglenia ich sumy. Wymaganie zadania decyduje, która procedura jest właściwa.

NULL i bezpieczny mianownik

-- SQLite, MySQL / MariaDB, SQL Server i Oracle (w zapytaniu z FROM)
SELECT cena / NULLIF(0, 0) AS bez_dzielenia_przez_zero
FROM produkty;

NULLIF(a,b) zwraca NULL, gdy a i b są równe, w innym razie a. Zamiast zera w realnym zadaniu podajesz kolumnę mianownika. Wynik NULL oznacza tutaj brak możliwego ilorazu; nie zamieniaj go automatycznie na zero, bo zero jest konkretnym wynikiem. Różne silniki i ustawienia inaczej reagują na zwykłe dzielenie przez zero. Jawna reguła ogranicza nieporozumienia.

Ćwiczenia

  1. Pokaż ceny produktów po rabacie 15%, zaokrąglone do dwóch miejsc.
  2. W SQLite porównaj 9/4 i 9.0/4. Wyjaśnij różnicę.
  3. Oblicz odległość ceny każdego produktu od 100, bez znaku.
Rozwiązania
SELECT nazwa, ROUND(cena * 0.85, 2) AS cena_85
FROM produkty ORDER BY id;
SELECT 9 / 4 AS integer_wynik, 9.0 / 4 AS real_wynik;
SELECT nazwa, ABS(cena - 100) AS odleglosc
FROM produkty ORDER BY id;

1. 102, 51, 680, 21.25. 2. 2 oraz 2.25: decydują typy operandów. 3. 20, 40, 700, 75. SELECT tylko pokazuje obliczenia, więc reset nie jest potrzebny do cofania tych odczytów.

Źródła: MySQL — zaokrąglanie, SQL Server ROUND, Oracle ROUND, Access/VBA Round. INF.03.4: wyrażenia i przetwarzanie danych. Dalej: daty, konwersje i wyrażenia warunkowe.

Przewijanie do góry