Сметки в заявката
Накратко: В SELECT можеш да смяташ с колоните (+, -, *, /) за всеки ред и да закръгляш с ROUND, но в SQLite, PostgreSQL и SQL Server делението на две цели числа отрязва дробната част.
Проблем
Колко струва този ред?
Счетоводството иска за всеки ред от поръчка колко струва: количеството по цената. В таблицата order_items има само двете числа:
В поръчка 3 има ябълки, 4 по 2,10 €, и прах за пране, 3 по 12,50 €. Да смяташ на ръка за 152 реда не е работа за човек. А да пазиш сумата в още една колона значи да я поддържаш вярна при всяка промяна.
Идеята
Колона, която се смята
В SELECT освен колони може да пишеш и изрази: сметки с колоните. Базата ги пресмята за всеки ред:
Знаците са +, -, *, / и % (остатък при деление). Името на сметнатата колона е самият израз, затова ѝ даваш кратко име с AS. Таблицата не се променя: сметката е само в резултата.
По псевдонима може и да подредиш. Петте най-скъпи реда от всички поръчки:
Изразът може и без таблица. Тогава SELECT пресмята веднъж, като калкулатор. Умножението е преди събирането, а скобите сменят реда:
Пробвай
Цената с ДДС
Цените в базата са без ДДС. Покажи името, цената и цената с 20% ДДС в колона with_vat.
Решение
SELECT name, price, price * 1.2 AS with_vat FROM products;price * 1.2 AS with_vat. С 20% отгоре цената е 120% от старата, тоест 1,2 пъти. Бял хляб излиза 1,44 €. Тук проверката гледа и имената на колоните.
Виж го
Оценката в проценти
Сайтът иска да показва оценките от 1 до 5 като проценти: 5 е 100%, 4 е 80%. Пусни:
Това е целочислено деление. Когато и двете числа са цели, резултатът също е цял:
Щом едното число е дробно (2.0) или е превърнато в дробно с CAST(… AS REAL), и делението е дробно. За процентите е достатъчно да умножиш първо, по 100.0:
При price този капан го няма: цената е дробно число (REAL). Пази се при колоните с цели числа, като rating, quantity и stock.
По-точно, за любопитните
PostgreSQL и SQL Server делят целите числа по същия начин: 5 / 2 е 2. MySQL прави обратното: там 5 / 2 е 2.5000, а за целочислено деление има DIV. Делението на нула в SQLite дава NULL, а в PostgreSQL е грешка.
Идеята
ROUND: до цент
Промоция: −15% на млечните. Новата цена е 85% от старата:
Кисело мляко за 0,935 € не може да се плати. ROUND(x, 2) закръгля до две цифри след точката, тоест до цент. ROUND(x) закръгля до цяло число.
Погледни сиренето: 6,715 стана 6,71, а не 6,72. Защо, виж отдолу.
По-точно, за любопитните
Дробните числа в компютъра се пазят в двоична система, а там 0,1 няма точен запис, както 1/3 няма точен запис с десетични цифри. Затова:
На екрана е 0,3, но на сравнението базата казва „не“ (0). printf с %!.20f показва какво е записано наистина. Същото е със сиренето: 7,9 × 0,85 в паметта е 6,71499…, и ROUND честно го закръгля надолу.
Затова в истинските системи парите не се пазят като REAL. Пазят се в цели центове (1,20 € е 120), или в тип за точни десетични числа: NUMERIC(10, 2) или DECIMAL(10, 2) в PostgreSQL, MySQL и SQL Server. В SQLite такъв тип няма, затова там се ползват центове:
С центове 790 × 85 е точно 67 150, а делението на 100 дава 671,5 цента, които се закръглят до 672, тоест 6,72 €.
Пробвай
Промоцията
Покажи името, цената и промоционалната цена на всички продукти. Промоционалната е price * 0.85, закръглена до цент, в колона sale_price.
Решение
SELECT name, price, ROUND(price * 0.85, 2) AS sale_price FROM products;ROUND(price * 0.85, 2) AS sale_price. ROUND обвива целия израз: първо се смята, после се закръгля.
Упражнение
Две задачи
1. Застрахователят пита колко струва стоката в склада. Покажи петте продукта с най-голяма стойност на наличността (цена по наличност), най-голямата първа. Подаръчната карта не е стока на рафта: остави само продуктите с категория.
Име, наличност и stock_value, петте най-големи:
Решение
SELECT name, stock, price * stock AS stock_value
FROM products
WHERE category_id IS NOT NULL
ORDER BY stock_value DESC
LIMIT 5;price * stock AS stock_value, WHERE category_id IS NOT NULL, ORDER BY stock_value DESC LIMIT 5. Първо е кафето на зърна: 15 пакета по 14,90 € са 223,50 €. Тук проверката гледа и реда.
2. Стоката пристига в кашони по 12 бройки. За всеки продукт с категория, който е в наличност, покажи колко пълни кашона са (boxes) и колко бройки остават извън тях (loose).
Име, наличност, boxes и loose:
Решение
SELECT name, stock, stock / 12 AS boxes, stock % 12 AS loose
FROM products
WHERE stock > 0 AND category_id IS NOT NULL;stock / 12 AS boxes, stock % 12 AS loose. Тук целочисленото деление е точно това, което искаш: 40 хляба са 3 пълни кашона и 4 бройки отделно.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: SELECT: избор на колони · WHERE: филтриране на редове · NULL: няма стойност · ORDER BY, LIMIT и DISTINCT
- Продължава в: Текстови функции · Функции за дати · CASE и липсващите стойности · Агрегатни функции: COUNT, SUM, AVG
- Задачи по темата: Изрази и функции