Совсем недавно я написал в блоге о выпуске 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
где
condition
— любое выражение, которое оценивается как результат типаboolean
[…]
Меня поразило, как молния, когда я прочитал этот вопрос переполнения стека . Вы можете поставить предикат везде! Хотя я знал это раньше, я никогда не думал о том, как это круто! Вы можете использовать предикаты в предложении SELECT:
1
2
|
SELECT a, b, c = d, e IN ( SELECT x FROM y) FROM t |
Вы можете использовать предикаты в предложении GROUP BY:
1
2
3
|
SELECT count (*) FROM t GROUP BY c = d, e IN ( SELECT x FROM y) |
Вы можете использовать предикаты в предложении ORDER BY:
1
2
3
|
SELECT * FROM t ORDER BY c = d, e IN ( SELECT x FROM y) |
Вы можете агрегировать предикаты, используя КАЖДУЮ функцию агрегирования .
Не верь этому? Убедитесь сами в этом SQLFiddle !
«Обычный» SQL
В «обычном» SQL (то есть в соответствии со стандартами) предикаты должны быть преобразованы в выражения обычных значений с помощью предложения CASE. Повторяя приведенные выше примеры:
Предложение SELECT:
1
2
3
4
5
|
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:
1
2
3
4
5
|
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:
1
2
3
4
5
|
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, например:
1
2
3
4
5
6
7
8
|
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 будут работать таким образом. Несмотря на то, что это здорово с точки зрения синтаксиса, следите за своими планами выполнения, чтобы убедиться, что это не приведет к множеству очень дорогих вложенных циклов …