CASE и липсващите стойности
Накратко: CASE WHEN връща различна стойност според условие, COALESCE слага стойност на мястото на NULL, а NULLIF превръща дадена стойност в NULL.
Проблем
Платена, а не paid
На страницата „Моите поръчки“ клиентът вижда състоянието както е в базата: paid, shipped. Кодовете на английски са удобни за програмата, но клиентът очаква „платена“ и „изпратена“.
Сайтът иска и филтър „евтини, средни, скъпи“. В базата няма такава колона, има само цена.
Идеята
CASE WHEN
CASE дава различна стойност според условие:
Условията се проверяват отгоре надолу. Първото вярно WHEN дава стойността на THEN до него, и останалите не се гледат. ELSE е за всички, за които нищо не е вярно. END затваря израза, а AS му дава име.
Когато сравняваш една колона с няколко стойности, има по-кратък запис: колоната се пише веднъж след CASE, а след всяко WHEN стои само стойността:
Пробвай
Състоянията с думи
Покажи номера, датата и състоянието с думи на всяка поръчка, в колона status_text: new е „нова“, paid е „платена“, shipped е „изпратена“, delivered е „доставена“, cancelled е „отказана“.
Решение
SELECT id, ordered_at,
CASE status
WHEN 'new' THEN 'нова'
WHEN 'paid' THEN 'платена'
WHEN 'shipped' THEN 'изпратена'
WHEN 'delivered' THEN 'доставена'
WHEN 'cancelled' THEN 'отказана'
END AS status_text
FROM orders;Пет WHEN в краткия запис CASE status … END AS status_text. Ако някой ден се появи ново състояние, без ELSE то ще излезе като NULL. Така поне ще го забележиш.
Виж го
Скъпите изчезнаха
Колега пренаписва ценовите групи с >. Пусни и виж кухнята:
Още нещо: ако няма ELSE, а нито едно WHEN не е вярно, резултатът е NULL. Хлябът има бележка само когато е изчерпан или е малко:
Понякога точно това искаш. Ако не, напиши ELSE.
Идеята
COALESCE и NULLIF
COALESCE(a, b, …) връща първата стойност, която не е NULL. Така се слага дума на мястото на липсващото:
Понякога „липсва“ е записано не като NULL, а като празен текст. В двата примера отдолу базата има още един клиент, Анна, записана през формуляр, който праща '' вместо NULL. COALESCE не я хваща, защото празният текст е стойност:
NULLIF(a, b) дава NULL, когато a е равно на b, иначе дава a. Така празният текст става NULL, а COALESCE хваща и двамата:
По-точно, за любопитните
NULLIF се ползва и за делене: total / NULLIF(count, 0). Когато count е 0, делителят става NULL и резултатът е NULL. В SQLite делението на нула и без това дава NULL, но в PostgreSQL е грешка и спира цялата заявка.
Пробвай
Редът за куриера
Поправи реда „име, град“ от урока за текст: когато градът липсва, на мястото му да пише „без град“. Колоната да се казва contact.
Решение
SELECT name || ', ' || COALESCE(city, 'без град') AS contact FROM customers;name || ', ' || COALESCE(city, 'без град') AS contact. Сега Борис Митев има ред: „Борис Митев, без град“.
Упражнение
Две задачи
1. До всеки продукт сайтът пише наличността с думи: „изчерпан“ при 0, „последни бройки“ под 10, иначе „в наличност“. Покажи името, наличността и думите в колона availability.
Наличността с думи за всеки продукт:
Решение
SELECT name, stock,
CASE
WHEN stock = 0 THEN 'изчерпан'
WHEN stock < 10 THEN 'последни бройки'
ELSE 'в наличност'
END AS availability
FROM products;Първо WHEN stock = 0, после WHEN stock < 10, накрая ELSE. Ако размениш първите две, изчерпаните ще са „последни бройки“, защото 0 също е под 10.
2. Складът работи в този ред: първо опакова платените (paid), после гледа новите (new), накрая проверява изпратените (shipped). Покажи номера, състоянието и датата на тези поръчки в реда на работа, а в едно състояние първо най-старата. При една и съща дата първо по-малкият номер.
Отворените поръчки в реда, в който складът ги обработва:
Решение
SELECT id, status, ordered_at
FROM orders
WHERE status IN ('paid', 'new', 'shipped')
ORDER BY CASE status WHEN 'paid' THEN 1 WHEN 'new' THEN 2 ELSE 3 END, ordered_at, id;ORDER BY CASE status WHEN 'paid' THEN 1 WHEN 'new' THEN 2 ELSE 3 END, ordered_at, id. CASE превръща състоянието в число за подреждане. Тук проверката гледа и реда.
По-точно, за любопитните
SQLite има и IIF(условие, ако е вярно, ако не е): кратък CASE с едно WHEN и ELSE. Има го и в SQL Server, но не и в PostgreSQL. CASE е стандартният запис и работи навсякъде.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: NULL: няма стойност · ORDER BY, LIMIT и DISTINCT · Сметки в заявката · Текстови функции
- Продължава в: Агрегатни функции: COUNT, SUM, AVG · Много таблици и таблица със себе си · Отчет на стъпки: WITH · Дървета и редици: WITH RECURSIVE
- Задачи по темата: Изрази и функции