Язык SQL и его глубина … Некоторые из вас, читатели, могут знать о возможности MySQL по подсчету различных записей с помощью агрегатной функции COUNT (). Документация MySQL гласит:
COUNT(DISTINCTexpr,[expr...])Возвращает счетчик количества строк с разными
exprзначениямиexpr.
Другими словами, вы можете очень легко считать разные имена и фамилии:
|
1
2
|
SELECT COUNT(DISTINCT FIRST_NAME, LAST_NAME)FROM CUSTOMERS |
Это довольно полезно, но специфично для MySQL ( хотя HSQLDB также поддерживает этот конкретный синтаксис MySQL ). Большинство других баз данных, однако, не предлагают такую функцию, даже если стандарт SQL-99 уже определил ее:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
6.16 <set function specification><set function specification> ::= COUNT <left paren> <asterisk> <right paren> | <general set function><general set function> ::= <set function type> <left paren> [ <set quantifier> ] <value expression> <right paren><set function type> ::= <computational operation><computational operation> ::= AVG | MAX | MIN | SUM | EVERY | ANY | SOME | COUNT<set quantifier> ::= DISTINCT | ALL |
Выше было позже объединено в 10.9 <агрегатная функция> в SQL: 2011 со множеством других типов и функций агрегатных функций. Теперь давайте посмотрим на 6.23 <выражение значения>:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
6.23 <value expression><value expression> ::=<numeric value expression>| <string value expression>| <datetime value expression>| <interval value expression>| <boolean value expression>| <user-defined type value expression>| <row value expression> <-- RVE!| <reference value expression>| <collection value expression> |
Интересно, что вы можете поместить выражение значения строки в некоторые из ваших агрегатных функций. Существуют дополнительные ограничения, например, вы не можете SUM() или AVG() . Но с COUNT() и COUNT(DISTINCT ...) это имеет смысл. Таким образом, в соответствии со стандартом SQL (и в соответствии с альтернативой HSQLDB и основной реализацией PostgreSQL, которая, к сожалению, на самом деле не документирована), следующий способ будет правильным способом подсчитывать разные имена и фамилии в SQL:
|
1
2
|
SELECT COUNT(DISTINCT (FIRST_NAME, LAST_NAME))FROM CUSTOMERS |
… что имеет смысл. Будьте внимательны при чтении этого. Это не функция DISTINCT() ! Это ключевое слово DISTINCT применяемое к выражению значения строки. Смотрите некоторые предыдущие сообщения в блоге о выражениях значения строки здесь:
- Забава преобразования запроса SQL: предикаты с выражениями значения строки
- Выражение значения строки и предикат BETWEEN
- Выражение значения строки и предикат NULL
jOOQ стандартизирует различные диалекты SQL и скрывает вышеуказанное за DSL.countDistinct() .
Когда вы не используете HSQLDB, MySQL или PostgreSQL
В других базах данных вы можете прибегнуть к ручному преобразованию SQL. Наш пример легко трансформируется:
|
1
2
3
4
5
|
SELECT COUNT(*)FROM ( SELECT DISTINCT FIRST_NAME, LAST_NAME FROM CUSTOMERS) t |
Но такое преобразование запроса может оказаться сложным, если у вас есть предложения GROUP BY или другие агрегатные функции. Будущие версии jOOQ могут сделать для вас такую трансформацию.