В недавнем прошлом мы объяснили синтаксические последствия предложения SQL GROUP BY. Если вы еще этого не сделали, вам следует прочитать нашу статью « Действительно ли вы понимаете SQL-предложения GROUP BY и HAVING? «.
По сути, добавление предложения GROUP BY
к вашему запросу преобразует ваш запрос на очень неявные уровни. Следующее напоминание суммирует предыдущую статью:
- Только выражения столбца, на которые есть ссылка в предложении
GROUP BY
, или агрегаты других выражений столбца могут появляться в предложенииSELECT
- Агрегации без явного предложения
GROUP BY
подразумевают «итоговое» предложениеGROUP BY ()
- Некоторые базы данных ( например, MySQL и, в некоторой степени: стандарт SQL) не следуют этим правилам и допускают произвольные выражения столбцов (или, по крайней мере, функционально зависимые выражения столбцов) в предложении
SELECT
Как должен был быть разработан SQL GROUP BY
Существует еще один способ взглянуть на GROUP BY
, и он был реализован на столь же увлекательном, красивом и странном языке запросов Cypher (это хорошие атрибуты), который поддерживается графовой базой данных Neo4j . Этот альтернативный (все еще вдохновленный SQL) язык запросов, вероятно, заслуживает отдельной серии постов в блоге, но давайте сосредоточимся на агрегации. Поскольку агрегация является основным вариантом использования для группировки.
- (для записи, посмотрите документы Neo4j об агрегации для деталей)
Краткий обзор, чтобы понять Cypher:
Рассмотрим этот простой запрос Cypher:
1
2
3
4
5
|
MATCH (me:Person)-->(friend:Person) -->(friend_of_friend:Person) WHERE me.name = 'A' RETURN count(DISTINCT friend_of_friend), count(friend_of_friend) |
- Cypher
MATCH
соответствует SQLFROM
- Сайфер,
WHERE
… сделать обоснованное предположение - Cypher
RETURN
соответствует SQLSELECT
( и он помещен в семантически более полезное место )
более того
- зашифровывать
12
(me:Person)-->(friend:Person)
-->(friend_of_friend:Person)
примерно соответствует SQL
12345Person
AS
me
JOIN
Person
AS
friend
ON
[ implicit equi-
join
predicate ]
JOIN
Person
as
friend_of_friend
ON
[ implicit equi-
join
predicate ]
Написание Cypher JOIN
на самом деле чрезвычайно полезно и может также применяться к SQL. Это только вопрос времени, когда кто-то напишет преобразователь Cypher-to-SQL, который реализует синтаксис, по крайней мере, как синтаксический сахар для эквивалентной нотации равного соединения ANSI.
Давайте исследуем агрегацию в Cypher
Вот запрос снова:
1
2
3
4
5
|
MATCH (me:Person)-->(friend:Person) -->(friend_of_friend:Person) WHERE me.name = 'A' RETURN count(DISTINCT friend_of_friend), count(friend_of_friend) |
Итак, в терминах SQL это точно так же, как:
1
2
3
4
|
SELECT count ( DISTINCT friend_of_friend), count (friend_of_friend) FROM [ Persons ... ] WHERE me. name = 'A' |
Другими словами, подразумевается один и тот же неявный общий итог GROUP BY ()
и все значения объединяются в одну строку.
Следующий пример из документации Neo4j более интригующий. Это будет подсчитывать количество узлов, подключенных к узлу n
с name = 'A'
:
1
2
|
MATCH (n { name: 'A' })-->(x) RETURN n, count(*) |
Что является более короткой формой для письма:
1
2
3
|
MATCH (n)-->(x) WHERE n.name = 'A' RETURN n, count(*) |
В этом примере также будет выполняться агрегация, но на этот раз с неявным предложением GROUP BY n
. В SQL вы бы написали что-то вроде:
1
2
3
4
5
6
|
SELECT n.id, count (*) FROM n JOIN x ON [ implicit equi- join predicate ] WHERE n. name = 'A' GROUP BY n.id |
Хорошая вещь в Cypher заключается в том, что подразумевается очевидное предложение GROUP BY
(оно может быть только GROUP BY n.id
). Это не должно быть написано явно.
Еда на вынос для SQL
Мы видели несколько замечательных возможностей языка Cypher, особенно невероятно хороший способ написать «JOIN» (или, скорее, обход графов в Neo4j). Но гораздо более очевидным, низко висящим плодом с реальными шансами включить его в стандарт SQL было бы сделать предложение SQL GROUP BY
необязательным и зависящим от предложения SELECT
с использованием следующих правил:
- Если
SELECT
содержит функций агрегирования, не должно быть подразумеваемого предложенияGROUP BY
- Если
SELECT
содержит 1-N функций агрегирования, то из оставшихся столбцов должно быть подразумеваемое предложениеGROUP BY
- Если
SELECT
содержит только функции агрегирования, применяетсяGROUP BY ()
общего итога - Явное предложение
GROUP BY
всегда будет предпочтительнее любого подразумеваемого предложенияGROUP BY
Если кто-то из членов комитета ИСО / МЭК читает это, это мой список пожеланий для будущего стандарта SQL. И, пожалуйста, PostgreSQL. Реализуйте это прямо сейчас.
Понравилась эта статья?
Вот еще немного о предложении SQL GROUP BY
и агрегации:
- Руководство Neo4j об агрегации
- Как перевести SQL GROUP BY и агрегаты в Java 8
- Вы действительно понимаете SQL-предложения GROUP BY и HAVING?
- GROUP BY ROLLUP / CUBE
- Как использовать SQL PIVOT для сравнения двух таблиц в вашей базе данных
- Awesome PostgreSQL 9.4 / SQL: 2003 FILTER для агрегатных функций
- Драгоценный камень SQL, о котором вы еще не знали: агрегатная функция EVERY ()
Ссылка: | Как должен был быть создан SQL GROUP BY — как и неявная GROUP BY от Neo4j от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ . |