Использование констант в SELECT-запросах SQL

Любите ли вы «магические числа» в коде? Все эти 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.