Этот вопрос уже имеет ответ здесь:
Я часто нахожу эти три варианта:
SELECT COUNT(*) FROM Foo;
SELECT COUNT(1) FROM Foo;
SELECT COUNT(PrimaryKey) FROM Foo;
Насколько я вижу, они все делают то же самое, и я использую три в своей кодовой базе. Однако мне не нравится делать то же самое различные пути. Которого я должен придерживаться? Кто-либо из них лучше, чем оба другие?
Использование либо COUNT (поле)
, либо 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 *
не имеют отношения друг к другу, это совершенно разные вещи, они просто имеют общий токен, т.е. *
.
Фактически, если не разрешено называть поле таким же, как имя его таблицы, разработчик языка СУБД может дать COUNT (tableNameHere)
ту же семантику, что и СЧЕТЧИК (*)
. Пример:
Для подсчета строк мы могли бы иметь это:
SELECT COUNT(emp) FROM emp
И они могли бы упростить:
SELECT COUNT() FROM emp
А для ЛЕВЫХ СОЕДИНЕНИЙ мы могли бы иметь это:
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's say, someone forgot to put NOT NULL */
shape varchar(50) NOT NULL,
color varchar(50) NOT NULL
)
Кроме того, не рекомендуется делать поле допускающим значение NULL, если его имя совпадает с имя таблицы. Допустим, у вас есть значения Banana, Apple, NULL, Pears в поле fruit
.Это не будет считать все строки, это даст только 3, а не 4
SELECT count(fruit) FROM fruit
. Хотя некоторые СУБД используют такой принцип (для подсчета строк таблицы она принимает имя таблицы как параметр COUNT), это будет работать в Postgresql (если есть не является подчиненным
полем ни в одной из двух приведенных ниже таблиц, т. е. пока нет конфликта имен между именем поля и именем таблицы):
SELECT boss.boss_id, COUNT(subordinate)
FROM boss
LEFT JOIN subordinate on subordinate.boss_id = boss.boss_id
GROUP BY boss.id
Но это может вызвать путаницу позже, если мы добавим подчиненное
поле в таблице, так как оно будет подсчитывать поле (которое может иметь значение NULL), а не строки таблицы.
На всякий случай используйте:
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 (подчиненный. *)
Так что просто используйте одно из следующих:
-- 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
Я чувствую, что характеристики производительности меняются от одной СУБД к другой. Все зависит от того, как они это хотят реализовать. Поскольку я много работал над Oracle, я расскажу с этой точки зрения.
COUNT (*)
- извлекает всю строку в набор результатов перед переходом к функции count, функция count будет агрегировать 1, если строка не равна нулю
COUNT (1)
- не будет извлекаться любая строка, вместо этого вызывается count с постоянным значением 1 для каждой строки в таблице, когда совпадает WHERE
.
COUNT (PK)
- PK в Oracle индексируется. Это означает, что Oracle должен читать только индекс. Обычно одна строка в дереве индекса B + во много раз меньше, чем фактическая строка.Таким образом, учитывая скорость дискового ввода-вывода в секунду, Oracle может получить во много раз больше строк из индекса с помощью передачи одного блока по сравнению со строкой целиком. Это приводит к более высокой пропускной способности запроса.
Из этого видно, что первый счет самый медленный, а последний счет самый быстрый в Oracle.
Два из них всегда дают один и тот же ответ:
COUNT(*)
подсчитывает количество строкCOUNT(1)
также подсчитывает количество строкЕсли предположить, что pk
является первичным ключом и в значениях не допускаются нули, то
COUNT(pk)
также подсчитывает количество строкОднако, если pk
не ограничен значением not null, то получается другой ответ:
COUNT(possibly_null)
подсчитывает количество строк с ненулевыми значениями в столбце possibly_null
.
COUNT(DISTINCT pk)
также подсчитывает количество строк (поскольку первичный ключ не допускает дубликатов).
COUNT(DISTINCT possibly_null_or_dup)
подсчитывает количество отдельных не нулевых значений в столбце possibly_null_or_dup
.
COUNT(DISTINCT possibly_duplicated)
подсчитывает количество отдельных (обязательно ненулевых) значений в столбце possibly_duplicated
, если в нем есть оговорка NOT NULL
.
Обычно я пишу COUNT(*)
; это оригинальная рекомендуемая нотация для SQL. Аналогично, в предложении EXISTS
я обычно пишу WHERE EXISTS(SELECT * FROM ...)
, потому что это первоначальная рекомендуемая нотация. Альтернативные варианты не должны иметь никаких преимуществ; оптимизатор должен видеть более непонятные обозначения.
Это будет зависеть от типа используемой базы данных, а также от типа таблицы в некоторых случаях.
Например, при использовании MySQL, count(*)
будет быстрым в таблице MyISAM, но медленным в InnoDB. В InnoDB вы должны использовать count(1)
или count(pk)
.
По крайней мере, на Oracle они все одинаковые: http://www.oracledba.co.uk/tips/count_speed. htm
Спрашивали и отвечали раньше...
Книга в интернете говорит:«COUNT ( { [ [ ВСЕ | ОТДЕЛЬНОЕ выражение ] | * } )
"
"1" является ненулевым выражением, поэтому оно совпадает с COUNT(*)
.
Оптимизатор признает его тривиальным , поэтому дает тот же план. PK уникален и не равен нулю (по крайней мере, в SQL Server), поэтому COUNT(PK)
= COUNT(*)
Это миф, похожий на EXISTS (SELECT * ...
или СУЩЕСТВУЕТ (ВЫБЕРИТЕ 1 ...
И см. спецификация ANSI 92, раздел 6.5, Общие правила, случай 1
a) If COUNT(*) is specified, then the result is the cardinality
of T.
b) Otherwise, let TX be the single-column table that is the
result of applying the <value expression> to each row of T
and eliminating null values. If one or more null values are
eliminated, then a completion condition is raised: warning-
null value eliminated in set function.