Статьи

Почему PostgreSQL такой классный

Совсем недавно я написал в блоге о выпуске PostgreSQL 9.3 , что достаточно удивительно, поскольку PostgreSQL наконец поддерживает материализованные и обновляемые представления. Затем я написал в блоге о том, что синтаксис PostgreSQL является загадкой, превышающей его мощь , поскольку он позволяет рассматривать операторы INSERT и UPDATE как ссылки на таблицы при использовании с предложением RETURNING. Это довольно необычно, даже если не очень полезно в повседневном SQL.

Но то, о чем я пишу сегодня, колоссально:

Предикаты PostgreSQL — это просто обычные выражения

Пусть это впитывается. Для PostgreSQL предикаты — это просто обычные выражения, вычисляющие логический тип. Это задокументировано в синтаксической справке SELECT здесь:
http://www.postgresql.org/docs/9.3/static/sql-select.html.

Цитирование:

Необязательное предложение WHERE имеет общую форму:

WHERE condition

Где условие — любое выражение, которое оценивается как результат типа Boolean […]

Меня поразило, как молния, когда я прочитал этот вопрос переполнения стека . Вы можете поставить предикат везде! Хотя я знал это раньше, я никогда не думал о том, как это круто! Вы можете использовать предикаты в предложении SELECT:

SELECT a, b, c = d, e IN (SELECT x FROM y)
FROM t

Вы можете использовать предикаты в предложении GROUP BY:

SELECT count(*)
FROM t
GROUP BY c = d, e IN (SELECT x FROM y)

Вы можете использовать предикаты в предложении ORDER BY:

SELECT *
FROM t
ORDER BY c = d, e IN (SELECT x FROM y)

Вы можете агрегировать предикаты, используя КАЖДУЮ функцию агрегирования .

Не верь этому? Убедитесь сами в этом SQLFiddle !

«Обычный» SQL

В «обычном» SQL (т. Е. В соответствии со стандартами) предикаты должны быть преобразованы в выражения с обычными значениями с помощью предложения CASE. Повторяя приведенные выше примеры:

Предложение SELECT:

SELECT a, b,
       CASE WHEN c = d THEN true ELSE false END,
       CASE WHEN e IN (SELECT x FROM y)
            THEN true ELSE false END
FROM t

Предложение GROUP BY:

SELECT count(*)
FROM t
GROUP BY CASE WHEN c = d THEN true ELSE false END,
         CASE WHEN e IN (SELECT x FROM y)
              THEN true ELSE false END

Предложение ORDER BY:

SELECT *
FROM t
ORDER BY CASE WHEN c = d THEN true ELSE false END,
         CASE WHEN e IN (SELECT x FROM y)
              THEN true ELSE false END

Влияние на JOOQ

Ответ дается в приведенном выше переполнении стеки вопрос показывает , как jOOQ может стандартизировать это поведение рендеринга предикатов и условия непосредственно в качестве выражений столбцов , где это поддерживается, в то время как эмулирующее это поведение , используя эквивалентное выражение CASE, в противном случае.

Возьмите предикаты в предложении SELECT, например:

DSL.using(configuration)
   .select(
       T.A, T.B,
       // Transform a jOOQ Condition into a Field:
       field(T.C.eq(T.D)),
       field(T.E.in(select(Y.X).from(Y)))
   )
   .from(T);

Дальнейшие мысли

Из опыта тестирования интеграции jOOQ я могу сказать, что Derby, H2, HSQLDB, MariaDB, MySQL, PostgreSQL и SQLite будут работать таким образом. Несмотря на то, что это здорово с точки зрения синтаксиса, следите за своими планами выполнения, чтобы убедиться, что это не приведет к множеству очень дорогих вложенных циклов …