Почему подстановочные знаки в операторах GROUP BY не работают?

29

Я пытаюсь заставить работать следующий оператор SQL, но получаю синтаксическую ошибку:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.*

Здесь A - это широкая таблица с 40 столбцами, и я хотел бы избежать перечисления каждого имени столбца в предложении GROUP BY, если это возможно. У меня есть много таких таблиц, по которым мне нужно выполнить аналогичный запрос, поэтому мне придется написать хранимую процедуру. Какой лучший способ подойти к этому?

Я использую MS SQL Server 2008.

Аноним Максимус
источник

Ответы:

32

GROUP BY A.* не допускается в SQL.

Вы можете обойти это, используя подзапрос, по которому вы группируете, а затем присоединитесь:

SELECT A.*, COALESCE(B.cnt, 0) AS Count_B_Foo
FROM TABLE1 AS A
  LEFT JOIN 
      ( SELECT FKey, COUNT(foo) AS cnt
        FROM TABLE2 
        GROUP BY FKey
      ) AS B 
    ON A.PKey = B.FKey ;

В стандарте SQL-2003 есть функция, позволяющая включать в SELECTсписок столбцы, которых нет в GROUP BYсписке, если они функционально зависят от них. Если бы эта функция была реализована в SQL-сервере, ваш запрос мог бы быть написан так:

SELECT A.*, COUNT(B.foo)
FROM TABLE1 A
LEFT JOIN TABLE2 B ON A.PKey = B.FKey
GROUP BY A.pk                          --- the Primary Key of table A

К сожалению, эта функция еще не реализована, даже в версии SQL-Server 2012 - и, насколько я знаю, ни в какой другой СУБД. За исключением MySQL, который имеет его, но неадекватно (неадекватно: вышеуказанный запрос будет работать, но механизм не будет проверять функциональную зависимость, а другие плохо написанные запросы будут показывать неправильные, полуслучайные результаты).

Как сообщил нам @Mark Byers в комментарии, PostgreSQL 9.1 добавил новую функцию, предназначенную для этой цели. Это более ограничительно, чем реализация MySQL.

ypercubeᵀᴹ
источник
Можете ли вы упомянуть пару СУБД, которые реализуют эту часть стандарта в письменном виде? Я знаю, например, что MySQL позволит вам (при условии правильных настроек) включать элементы, не входящие в GROUP BYпредложение в SELECTсписке, но он не определяет , из какой строки будет получено это значение (поэтому, если столбец или выражение не не зависит от выражения группировки, то оно может быть из любой строки в группе).
Адам Робинсон
@ Adam: Нет, я не знаю ни одной СУБД, в которой она реализована. У MySQL это есть, но неадекватно, как говорится в вашем комментарии.
ypercubeᵀᴹ
Попался. Я на самом деле спрашивал, были ли они, поскольку у меня есть опыт работы с гораздо меньшим количеством СУРБД, чем я себе представляю, большинство людей, отвечающих на вопросы на этом сайте;) Но это было мое подозрение.
Адам Робинсон
3
«и не в любой другой СУБД, насколько я знаю». PostgreSQL 9.1 добавил новую функцию, разработанную для этой цели. Это более ограничительно, чем реализация MySQL.
Марк Байерс
@MarkByers: спасибо, я этого не знал.
ypercubeᵀᴹ
24

В дополнение к обходному пути @ ypercube, «печатание» никогда не является оправданием для использования SELECT *. Я писал об этом здесь , и даже с обходным путем, я думаю, ваш SELECTсписок должен по-прежнему включать имена столбцов - даже если их огромное количество, например, 40.

Короче говоря, вы можете избежать ввода этих больших списков, щелкнув и перетащив узел Столбцы для объекта в обозревателе объектов в окно запроса. Снимок экрана показывает вид, но то же самое можно сделать для стола.

введите описание изображения здесь

Но если вы хотите прочитать обо всех причинах, по которым вы должны подвергать себя такому огромному уровню усилий при перетаскивании элемента на несколько дюймов, прочитайте мой пост . :-)

Аарон Бертран
источник
В PostgreSQL (с EMS SQL Manager) я делаю это, определяя представление, а SELECT *затем копирую список полей из определения представления.
Дезсо
Я, конечно, согласен, что SELECT *не следует использовать. Мне любопытно, GROUP BYхотя дело. @ Аарон, есть ли проблемы с эффективностью при наличии 40 столбцов в списке по группам?
ypercubeᵀᴹ
1
@ypercube - насколько я видел, если вы группируете по A.PK, A.some, A.other, A.columnsним, не стоит даже сравнивать, some, other, columnsэто просто требуется синтаксисом.
Мартин Смит
1
@datagod извините, нет, любые пробелы могут быть объяснены только командой разработчиков SSMS. :-)
Аарон Бертран
1
@Pacerier Извините, я полностью не согласен , но, возможно, вы могли бы уточнить.
Аарон Бертран