#sql #select #count
#sql #выберите #подсчитайте
Вопрос:
Я пытаюсь изучить SQL и выполняю упражнение, но я зациклен на том, почему этот простой SQL-оператор не будет работать.
select *, count(*) from bricks
Что пытается сделать инструктор, так это вернуть все строки таблицы с именем bricks. Мы также хотим добавить новый столбец в правую часть таблицы, который просто возвращает общее количество всех блоков в каждой записи. Итак, всего в таблице 6 блоков, поэтому в конце каждой строки должен быть столбец, который просто читается 6.
Инструктор сделал это следующим образом:
select b.*, (select count(*) from bricks) total_bricks_in_table from bricks b;
Первый запрос — это моя попытка, и я не понимаю, почему он не работает, поскольку выполняется
select * from bricks
и
select count(*) from bricks
Каждый работает сам по себе, но не в сочетании. Я пытался добавить оператор group by в конец моей попытки, но независимо от того, по какому столбцу я группирую, я все равно получаю ошибки. Что именно не так с моей первоначальной попыткой?
Комментарии:
1. Ваш 1-й Select возвращает 6 строк, а ваш 2-й — 1 строку, как DNMS должны это комбинировать? Если ваша СУБД поддерживает оконные агрегаты :
select *, count(*) OVER () from bricks
2. Синтаксис
select *, count(*) from bricks
искажен. Будьте осторожны, он устарел в MySQL 5.7.5 и новее (если вы не включаете старый синтаксис) по уважительной причине.3. @dnoeth Я думаю, это имеет смысл, но тогда как получается, что другой запрос с вложенным оператором select работает? Мне кажется, что он делает то же самое. Внутренняя инструкция select выполняется первой и возвращает одну строку со значением 6, и этот результат используется во внешней инструкции select, верно? Чем отличается тот, который заставляет его работать?
4. Внутренний select — это скалярный подзапрос , который логически выполняется для каждой строки, но оптимизатор обычно достаточно умен, чтобы видеть, что он всегда возвращает одно и то же значение и выполняет его только один раз.
5. Один
*
не может быть объединен ни с чем другим в списке выбора, согласно ISO / ANSI SQL.
Ответ №1:
Это потому, что COUNT
это агрегатная функция, и как только вы используете один агрегат, вам приходится выбирать, как агрегировать все остальные столбцы вашего SELECT
оператора.
Комментарии:
1. Итак, как мне выбрать способ агрегирования всех столбцов? Разве это не было бы сделано с помощью предложения GROUP BY? Как я уже говорил, я уже пробовал это и продолжаю получать ошибки. Кроме того, инструкция инструктора не использует group by и все еще работает.
2. На самом деле не имеет особого смысла (в SQL, то есть) иметь общее количество в каждой строке результата. На самом деле база данных не может этого сделать, поскольку для этого ей придется перебирать все записи. Итак, если вы сгруппируете все, в результате подсчета для каждой строки вы получите 1. Если вы все еще хотите, чтобы общее количество в каждой строке было таким, я использую подвыбор, как вы, который неэффективен, но сделает свое дело за вас.
3. Также попробуйте комментарий @dnoeth, если ваша СУБД это позволяет, это сработает.
Ответ №2:
Этот запрос:
select *, count(*)
from bricks
неверно сформирован. Из-за того, что count()
это агрегированный запрос. Запрос агрегации без group by
всегда возвращает одну строку. Однако вы также пытаетесь выбрать другие столбцы — любая разумная база данных будет следовать стандарту SQL и вернет ошибку.
Что вы можете сделать? В SQL есть нечто, называемое оконными функциями. Это позволяет довольно просто делать то, что вы хотите:
select *, count(*) over () as num_bricks
from bricks