Статьи

Почему 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

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

Справка: Почему PostgreSQL так хорош от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ .