Любите ли вы «магические числа» в коде? Все эти if (a == 259)… Никто их не любит. И SQL-запросов это касается в той же степени, как и языков программирования. «Магические» числа делают код нечитаемым, любые изменения в нём будут головной болью, и нужно всегда избегать их, если есть такая возможность. Итак, у вас есть потребность написать SELECT-запрос. И в нём есть какие-то сравнения с константами или выдача неких заранее определенных констант по условию. В то же время, просто объявить их в тексте запроса у вас не получится, нет такой операции. К счастью, коллективный разум нашёл решение.
Возьмём самый простой случай, когда вы хотите использовать какие-то числа для расчётов или выдачи. Подойдёт такое решение:
WITH consts AS (SELECT 3.14 AS pi, 2.68 AS e) SELECT some_table.col1, (CASE WHEN some_table.col1 < consts.pi THEN true ELSE false) AS less_than_pi, (CASE WHEN some_table.col1 < consts.e THEN true ELSE false) AS less_than_e FROM consts, some_table
Здесь мы выбираем значение col1 из таблицы some_table, а также в столбце less_than_pi выводим true, если col1 меньше числа пи, и false, если нет. То же самое для числа e. Обратите внимание, как в таблице consts мы определили используемые дальше константы, присоединили эту таблицу к основному запросу и использовали значения, хранящиеся в ней, в основном запросе.
Теперь давайте рассмотрим ситуацию, когда нам надо в константах использовать значения, полученные из другого запроса:
WITH consts AS (SELECT string_to_array(value, ',') AS types FROM some_settings WHERE key = 'some_key') SELECT some_table.col1, sum ( CASE WHEN (some_other_table.col1)::TEXT = ANY (consts.types) THEN 0 ELSE some_table.qty END) AS cnt FROM consts, (some_table t1 JOIN some_other_table t2 ON t1.id = t2.some_id )
Здесь мы предварительно забираем список типов (строка, из которой мы делаем массив), который находится в таблице с настройками tbl_settings, присваиваем его константе types, и далее уже используем её в расчётах.
Наконец, вот как можно обходиться с парами ключ-значение, которые мы хотим использовать в качестве констант:
WITH param_names AS ( SELECT * FROM (VALUES ('norm_hour', 'Нормочас'), ('price', 'Цена')) AS t (param_key, param_name) ) SELECT coalesce (param_names.param_name, '') AS param_to_show, some_table.param_value FROM some_table LEFT JOIN param_names on some_table.param_key = param_names.param_key
Здесь мы в param_names готовим наборы ключ-значение для человекопонятных названий неких параметров. param_key — это параметры (их ключи), хранимые в some_table. Данный запрос выдаёт понятные человеку названия параметров (определённые в константе) и их значения из some_table.