Почему этот простой SQL-запрос не работает? выберите *, count (*) из таблицы

#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