Почему COUNT() показывает только одну строку таблицы?
У меня есть следующая таблица pet
в базе данных menagerie
:
+--------+-------------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+-------------+---------+------+------------+------------+
| Tommy | Salman Khan | Lebre | NULL | 1999-01-13 | 0000-00-00 |
| Bowser | Diane | dog | m | 1981-08-31 | 1995-07-29 |
+--------+-------------+---------+------+------------+------------+
Теперь, если я запустил следующий запрос:
select owner, curdate() from pet;
Я получаю следующий вывод:
+-------------+------------+
| owner | curdate() |
+-------------+------------+
| Salman Khan | 2016-09-12 |
| Diane | 2016-09-12 |
+-------------+------------+
Вывод показывает все значения owner
и значение, возвращаемое с curdate()
в каждой строке.
Теперь, если я запустил следующий запрос:
select owner, count(*) from pet;
Я получаю следующий вывод:
+-------------+----------+
| owner | count(*) |
+-------------+----------+
| Salman Khan | 2 |
+-------------+----------+
Мой вопрос в том, какая разница между curdate()
и count()
функцией, которая позволяет MySQL
выводить вторую owner
Diane в первом примере?
Ответы
Ответ 1
COUNT()
- это функция агрегации, которая обычно объединяется с предложением GROUP BY
.
curdate()
- это функция даты, которая выводит текущую дату.
Только MySQL (насколько мне известно) допускает этот синтаксис без использования предложения GROUP BY
. Поскольку вы не предоставили его, COUNT(*)
будет считать общее количество строк в таблице, а столбец owner
будет выбран случайным образом/оптимизатор по умолчанию/по индексам.
Это должен быть ваш запрос:
select owner, count(*)
from pet
group by owner;
Сообщает оптимизатору подсчет полных строк, для каждого владельца.
Если упомянутое предложение по группе не указано - функции агрегации применяются ко всем данным таблицы.
EDIT: Счет, который будет применяться к каждой строке, обычно не может выполняться с помощью COUNT()
и обычно используется с аналитической функцией → COUNT() OVER(PARTITION...)
, которая, к сожалению, не существует в MySQL. Другой вариант - сделать JOIN/CORRELATED QUERY
для этого дополнительного столбца.
Другое Редактировать: Если вы хотите подсчитать количество рядом с каждым владельцем, вы можете использовать дополнительный запрос:
SELECT owner,
(SELECT COUNT(*) FROM pet) as cnt
FROM pet
Ответ 2
Это выглядит так же, как сценарий внизу этой страницы: Документация по MySQL: 4.3.4.8 Подсчет строк.
Если ONLY_FULL_GROUP_BY не включен, запрос обрабатывается обрабатывая все строки как одну группу, но значение, выбранное для каждого named column является неопределенным. Сервер может свободно выбирать значение из любой строки:
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT owner, COUNT(*) FROM pet;
+--------+----------+
| owner | COUNT(*) |
+--------+----------+
| Harold | 8 |
+--------+----------+
1 row in set (0.00 sec)
Я думаю, в этом случае only_full_group_by
не установлен.
Ответ 3
Только MySQL позволит вам делать такие запросы.
Вы всегда должны указывать все столбцы, которые не объединены с функцией агрегации в предложении GROUP BY
. Если нет, данные будут объединены в 1 строку, а агрегатные столбцы будут установлены правильно, а все остальные столбцы будут выбраны случайным образом или с индексами.
Итак, вам это нужно:
SELECT owner, count(*) FROM pet GROUP BY owner;
Что приведет к:
Saknan Khan | 1
Diane | 1
Это то, что вы намеревались достичь?
Или, может быть, вы попытались сделать это:
SELECT t.owner,
COUNT(*) as cnt
FROM pet t
CROSS JOIN pet s
GROUP BY t.owner
Это приведет к дополнительному столбцу с общим количеством отсчетов рядом с каждым владельцем.
Ответ 4
Большинство систем СУБД не позволят агрегатной функции, такой как count(), с дополнительными столбцами без группы; по причине. СУБД не знает, какие столбцы группировать: -).
Решение состоит в том, чтобы сгруппировать запрос по столбцу владельца, например:
SELECT owner, count(*) FROM pet GROUP BY owner;
Ответ 5
Функция подсчета (*) агрегата возвращает только одно значение и т.е. общее количество строк. И функция curdate() просто предоставляет текущую дату системы.
Ответ 6
Последний запрос недействителен для Oracle: ORA-00937: не одногрупповая функция. Это означает, что вам нужно предложение GROUP BY. Вы нашли лазейку в реализации MySql. Не полагайтесь на такой запрос в производственной системе, в следующей версии MySql это может не сработать.
Ответ 7
Да, это обычно происходит с использованием предложения group by.
http://www.w3schools.com/sql/sql_groupby.asp Вы должны прочитать в ссылке все о предложении group by.
Все столбцы следует упомянуть либо в виде агрегации, либо в группе с помощью