Ответ 1
Нижняя линия
Используйте либо COUNT(field)
, либо COUNT(*)
, и придерживайтесь его последовательно, и если ваша база данных позволяет COUNT(tableHere)
или COUNT(tableHere.*)
, используйте это.
Короче говоря, не используйте COUNT(1)
для чего-либо. Это одноходовой пони, который редко делает то, что вы хотите, и в этих редких случаях эквивалентно COUNT(*)
Используйте COUNT(*)
для подсчета
Используйте *
для всех ваших запросов, которые должны считать все, даже для соединений, используйте *
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Но не используйте COUNT(*)
для LEFT-соединений, так как это вернет 1, даже если подчиненная таблица ничего не сопоставляет с родительской таблицей
SELECT boss.boss_id, COUNT(*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Не обманывайтесь теми, кто советует, что при использовании *
в COUNT он извлекает целую строку из вашей таблицы, говоря, что *
работает медленно. *
на SELECT COUNT(*)
и SELECT *
не имеют отношения друг к другу, они совершенно разные, они просто разделяют общий токен, т.е. *
.
Альтернативный синтаксис
На самом деле, если не разрешено указывать поле так же, как имя его таблицы, разработчик языка RDBMS может предоставить COUNT(tableNameHere)
ту же семантику, что и COUNT(*)
. Пример:
Для подсчета строк мы могли бы иметь это:
SELECT COUNT(emp) FROM emp
И они могли бы сделать это проще:
SELECT COUNT() FROM emp
И для LEFT JOINs мы могли бы иметь это:
SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Но они не могут этого сделать (COUNT(tableNameHere)
), так как стандарт SQL позволяет называть поле с тем же именем, что и его имя таблицы:
CREATE TABLE fruit -- ORM-friendly name
(
fruit_id int NOT NULL,
fruit varchar(50), /* same name as table name,
and let say, someone forgot to put NOT NULL */
shape varchar(50) NOT NULL,
color varchar(50) NOT NULL
)
Подсчет с нулем
Кроме того, не рекомендуется делать поле нулевым, если его имя соответствует имени таблицы. Скажем, у вас есть значения "Банана", "Яблоко", "NULL", "Груши" в поле fruit
. Это не будет считать все строки, это даст только 3, а не 4
SELECT count(fruit) FROM fruit
Хотя некоторые СУБД выполняют такой принцип (для подсчета строк таблицы он принимает имя таблицы как параметр COUNT), это будет работать в Postgresql (если в любой из двух таблиц ниже нет поля subordinate
, т.е. если между именем поля и именем таблицы нет конфликта имен):
SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Но это может привести к путанице позже, если мы добавим в таблицу поле subordinate
, поскольку оно будет считать поле (которое может быть нулевым), а не строки таблицы.
Чтобы быть в безопасности, используйте:
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
COUNT(1)
: однопоточный пони
В частности, для COUNT(1)
, это одноконтактный пони, он работает только на одном запросе таблицы:
SELECT COUNT(1) FROM tbl
Но когда вы используете объединения, этот трюк не будет работать в многозадачных запросах, если его семантика не запутана и, в частности, вы не можете писать:
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.1)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Итак, что здесь означает значение COUNT (1)?
SELECT boss.boss_id, COUNT(1)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Разве это...?
-- counting all the subordinates only
SELECT boss.boss_id, COUNT(subordinate.boss_id)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Или это...?
-- or is that COUNT(1) will also count 1 for boss regardless if boss has a subordinate
SELECT boss.boss_id, COUNT(*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Соблюдая осторожность, вы можете сделать вывод, что COUNT(1)
совпадает с COUNT(*)
, независимо от типа соединения. Но для результата LEFT JOINs мы не можем формовать COUNT(1)
для работы как: COUNT(subordinate.boss_id)
, COUNT(subordinate.*)
Поэтому просто используйте одно из следующих действий:
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.boss_id)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Работает над Postgresql, ясно, что вы хотите подсчитать мощность множества
-- count the subordinates that belongs to boss
SELECT boss.boss_id, COUNT(subordinate.*)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Еще один способ подсчета мощности набора, очень английский (просто не создавайте столбец с именем, аналогичным имени его таблицы): http://www.sqlfiddle.com/#!1/98515/7
select boss.boss_name, count(subordinate)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name
Вы не можете этого сделать: http://www.sqlfiddle.com/#!1/98515/8
select boss.boss_name, count(subordinate.1)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name
Вы можете сделать это, но это приводит к неправильному результату: http://www.sqlfiddle.com/#!1/98515/9
select boss.boss_name, count(1)
from boss
left join subordinate on subordinate.boss_code = boss.boss_code
group by boss.boss_name