Статьи

Как должен был быть разработан SQL GROUP BY — как неявный GROUP BY в Neo4j

В недавнем прошлом мы объяснили синтаксические последствия предложения 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) язык запросов, вероятно, заслуживает отдельной серии постов в блоге, но давайте сосредоточимся на агрегации. Поскольку агрегация является основным вариантом использования для группировки.

Краткий обзор, чтобы понять 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)

более того

  • зашифровывать
    1
    2
    (me:Person)-->(friend:Person)
               -->(friend_of_friend:Person)

    примерно соответствует SQL

    1
    2
    3
    4
    5
    Person 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 и агрегации:

Ссылка: Как должен был быть создан SQL GROUP BY — как и неявная GROUP BY от Neo4j от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ .