Почему подстановочные знаки в операторах GROUP BY не работают?
29
Я пытаюсь заставить работать следующий оператор SQL, но получаю синтаксическую ошибку:
SELECT A.*, COUNT(B.foo)FROM TABLE1 ALEFTJOIN TABLE2 B ON A.PKey = B.FKeyGROUPBY A.*
Здесь A - это широкая таблица с 40 столбцами, и я хотел бы избежать перечисления каждого имени столбца в предложении GROUP BY, если это возможно. У меня есть много таких таблиц, по которым мне нужно выполнить аналогичный запрос, поэтому мне придется написать хранимую процедуру. Какой лучший способ подойти к этому?
Вы можете обойти это, используя подзапрос, по которому вы группируете, а затем присоединитесь:
SELECT A.*,COALESCE(B.cnt,0)AS Count_B_Foo
FROM TABLE1 AS A
LEFTJOIN(SELECT FKey, COUNT(foo)AS cnt
FROM TABLE2
GROUPBY FKey
)AS B
ON A.PKey = B.FKey ;
В стандарте SQL-2003 есть функция, позволяющая включать в SELECTсписок столбцы, которых нет в GROUP BYсписке, если они функционально зависят от них. Если бы эта функция была реализована в SQL-сервере, ваш запрос мог бы быть написан так:
SELECT A.*, COUNT(B.foo)FROM TABLE1 A
LEFTJOIN TABLE2 B ON A.PKey = B.FKey
GROUPBY A.pk --- the Primary Key of table A
К сожалению, эта функция еще не реализована, даже в версии SQL-Server 2012 - и, насколько я знаю, ни в какой другой СУБД. За исключением MySQL, который имеет его, но неадекватно (неадекватно: вышеуказанный запрос будет работать, но механизм не будет проверять функциональную зависимость, а другие плохо написанные запросы будут показывать неправильные, полуслучайные результаты).
Можете ли вы упомянуть пару СУБД, которые реализуют эту часть стандарта в письменном виде? Я знаю, например, что 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. :-)
GROUP BY
предложение вSELECT
списке, но он не определяет , из какой строки будет получено это значение (поэтому, если столбец или выражение не не зависит от выражения группировки, то оно может быть из любой строки в группе).В дополнение к обходному пути @ ypercube, «печатание» никогда не является оправданием для использования
SELECT *
. Я писал об этом здесь , и даже с обходным путем, я думаю, вашSELECT
список должен по-прежнему включать имена столбцов - даже если их огромное количество, например, 40.Короче говоря, вы можете избежать ввода этих больших списков, щелкнув и перетащив узел Столбцы для объекта в обозревателе объектов в окно запроса. Снимок экрана показывает вид, но то же самое можно сделать для стола.
Но если вы хотите прочитать обо всех причинах, по которым вы должны подвергать себя такому огромному уровню усилий при перетаскивании элемента на несколько дюймов, прочитайте мой пост . :-)
источник
SELECT *
затем копирую список полей из определения представления.SELECT *
не следует использовать. Мне любопытно,GROUP BY
хотя дело. @ Аарон, есть ли проблемы с эффективностью при наличии 40 столбцов в списке по группам?A.PK, A.some, A.other, A.columns
ним, не стоит даже сравнивать,some, other, columns
это просто требуется синтаксисом.