Конструкции CASE
Чтобы программа SQL могла принимать простейшие решения, не прибегая к процедурным языкам, в PostgreSQL поддерживаются конструкции CASE, предусмотренные стандартом SQL Ключевые слова SQL CASE, WHEN, THEN и END позволяют выполнять простые условные преобразования записей.
Вся конструкция CASE включается в целевой список команды SELECT. По умолчанию итоговому полю конструкции CASE присваивается имя case, но ему можно назначить синоним, как любому обычному полю. Общий синтаксис конструкции CASE в списке целей команды SELECT выглядит следующим образом:
CASE WHEN условие! THEN результат! WHEN условие2 THEN результат2 [… ] [ ELSE результат_по_умопчанию END [ AS синоним ]
Конструкция CASE-WHEN-THEN-ELSE отчасти напоминает условные команды if-then-else в традиционных языках программирования (листинг 4.50). Условия секций WHEN должны возвращать логический результат.
Если условие в секции WHEN выполняется, результат соответствующей секции THEN возвращается в поле итогового набора. Если ни одно условие не выполнено, можно задать значение по умолчанию в секции ELSE. Если при отсутствии секции ELSE результат остается неопределенным, возвращается NULL.
Листинг 4.50. Конструкции CASE в командах.
booktown=# SELECT isbn, booktown-# CASE WHEN cost > 20 THEN 'over $20.00 cost' booktown-# WHEN cost = 20 THEN '$20.00 cost1 booktown-# ELSE 'under $20.00 cost' booktown-# END AS cost_range booktown-# FROM stock booktown-# LIMIT 8; Isbn | cost_range 0385121679 | over $20.00 cost 039480001X | over $20.00 cost 044100590X | over $20.00 cost 0451198492 | over $20.00 cost 0394900014 | over $20.00 cost 0441172717 | under $20.00 cost 0451160916 | over $20.00 cost 0679803335 | $20.00 cost (8 rows)
Подзапросы PostgreSQL расширяют возможности конструкций CASE (см. раздел "Подзапросы"). Как показано в листинге 4.51, в качестве результата условного выражения в конструкции может быть задан подзапрос.
Листинг 4.51. Конструкции CASE в подзапросах.
booktown=# SELECT isbn, booktown-# CASE WHEN cost > 20 THEN 'N/A – (Out of price range)' booktown-# ELSE (SELECT title FROM books b JOIN editions e booktown(# ON (b.id = e.book_id) booktown(# WHERE e.isbn = stock.isbn) booktown-# END AS cost_range booktown-# FROM stock booktown-# ORDER BY cost_range ASC booktown-# LIMIT 8; isbn | cost_range 0451457994 | 2001: A Space Odyssey 0394800753 | Bartholomew and the Oobleck 0441172717 | Dune 0760720002 | Little Women 0385121679 | N/A – (Out of price range) 039480001X | N/A – (Out of price range) 044100590X | N/A – (Out of price range) 0451198492 | N/A – (Out of price range) (8 rows)
Для всех книг, цена которых не превышает 20, запрос возвращает название книги (подзапрос к таблице books) и код ISBN (основной запрос к таблице stock).