Совсем недавно я написал в блоге о выпуске 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 будут работать таким образом. Несмотря на то, что это здорово с точки зрения синтаксиса, следите за своими планами выполнения, чтобы убедиться, что это не приведет к множеству очень дорогих вложенных циклов …