У меня такой запрос:
select column_name, count(column_name)
from table
group by column_name
having count(column_name) > 1;
Какая была бы разница, если бы я заменил все вызовы с count(column_name) на count(*)?
Этот вопрос был вдохновлен Как найти повторяющиеся значения в таблице в Oracle?.
Чтобы прояснить принятый ответ (и, возможно, мой вопрос), замена count(column_name) на count(*) вернет дополнительную строку в результате, которая содержит null и количество значений null в столбце.


count(*) считает NULL, а count(column) - нет.
[edit] добавил этот код, чтобы люди могли его запускать
create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)
select count(*),count(id),count(id2)
from #bla
полученные результаты 7 3 2
Это стандарт для СУБД?
DB2 v9 выдает предупреждение: SQLSTATE 01003: значения NULL были исключены из аргумента функции столбца
Стоит отметить, что если у вас есть столбец, не допускающий значения NULL, такой как ID, то count (ID) значительно повысит производительность по сравнению с count (*).
@tsilb: ответ, опубликованный @Alan, гласит, что «count (*) вычисляется путем просмотра индексов в рассматриваемой таблице, а не фактических строк данных», что, если оно истинно, делает ваш комментарий недействительным. Я понимаю, что @Alan может ошибаться, но меня интересует источник вашей информации, чтобы выяснить, какой из них правильный.
@tsilb: многие современные оптимизаторы запросов оптимизируют count (*) для использования индексов, когда это имеет смысл.
Что интересно, это приводит к тому, что count (DISTINCT имя столбца) подсчитывает только отличные от NULL значения, тогда как SELECT DISTINCT также возвращает нулевую строку, если есть одно или несколько значений NULL.
@SQLMenace Что делать, если я использую count (1)? Что это меня оставит?
@renegadeMind: если ваша цель - просто проверить, что таблица не пуста при поиске конкретных условий, вы можете сделать это if Exists (Select 1 from sys.tables where name = 'SalesChannel_PartyRole')
Не должно быть улучшений в использовании count (column_name) по count (*), где column_name не равно нулю. любая выгода может быть получена от использования сканирования индекса вместо просмотра таблицы, но оптимизатор в любом случае может сделать это для count (*). В Oracle так было очень давно.
Неправильно говорить, что «count (*) подсчитывает нули» - наличие или отсутствие нулей не имеет значения, поскольку count (*) подсчитывает количество строк независимо от их содержимого.
@shannonSeverance, я считаю, что он действительно использует индекс в Mysql при использовании count (*) и count (1). Однако при использовании count (column_without_index) используется сканирование таблицы.
Объяснение в документы помогает объяснить это:
COUNT(*) returns the number of items in a group, including NULL values and duplicates.
COUNT(expression) evaluates expression for each row in a group and returns the number of nonnull values.
Итак, count (*) включает нули, а другой метод - нет.
Для новичков в SQL: к какому файлу справки вы имеете в виду?
Еще одно незначительное различие между использованием * и определенного столбца заключается в том, что в случае столбца вы можете добавить ключевое слово DISTINCT и ограничить счет отдельными значениями:
select column_a, count(distinct column_b)
from table
group by column_a
having count(distinct column_b) > 1;
Должны ли быть разные группы по столбцу и подсчитываемый? иначе вы бы ничего не получили из этого запроса
Да, извините .. Я не заметил, что в примере это одна и та же колонка. Я обновлю пост.
Еще одно и, возможно, тонкое отличие состоит в том, что в некоторых реализациях базы данных счетчик (*) вычисляется путем просмотра индексов в рассматриваемой таблице, а не фактических строк данных. Поскольку конкретный столбец не указан, нет необходимости беспокоиться о фактических строках и их значениях (как это было бы, если бы вы подсчитали конкретный столбец). Разрешение базе данных использовать данные индекса может быть значительно быстрее, чем подсчет «реальных» строк.
+1 Да, конечно, верно и для Oracle, и для PostgreSQL начиная с 9.2.
@DavidAldridge Можете ли вы предоставить указатель на документацию (особенно для postgresql), где это упоминается? Спасибо.
@Bhushan вот иди wiki.postgresql.org/wiki/Index-only_scans
Мы можем использовать Обозреватель данных Stack Exchange, чтобы проиллюстрировать разницу с помощью простого запроса. В таблице Users в базе данных Stack Overflow есть столбцы, которые часто остаются пустыми, например URL-адрес веб-сайта пользователя.
-- count(column_name) vs. count(*)
-- Illustrates the difference between counting a column
-- that can hold null values, a 'not null' column, and count(*)
select count(WebsiteUrl), count(Id), count(*) from Users
Если вы запустите приведенный выше запрос в Проводник данных, вы увидите, что счетчик одинаков для count(Id) и count(*), потому что столбец Id не допускает значений null. Однако количество WebsiteUrl намного ниже, потому что в этом столбце разрешен null.
Лучше всего использовать
Count(1) in place of column name or *
чтобы подсчитать количество строк в таблице, это быстрее, чем любой формат, потому что он никогда не проверяет имя столбца в таблице, существует или нет
Неправильно по крайней мере для Oracle, и я подозреваю, что для других СУБД тоже. Внутренне count (1) преобразуется в count (*). В частности, на производительность count (*) не влияет размер строк, что является распространенным заблуждением.
Это верно для SQL Server. Как сказал @Ali Adravi, COUNT(*) по сравнению с COUNT(columnName) не будет проверять значение столбца, потому что он просто перечисляет строки. Но COUNT(columnName) медленнее, даже count, примененный к колонке id! По крайней мере, в SQL Server, конечно.
См. Следующий код для выполнения тестов SQL Server 2008:
-- Variable table
DECLARE @Table TABLE
(
CustomerId int NULL
, Name nvarchar(50) NULL
)
-- Insert some records for tests
INSERT INTO @Table VALUES( NULL, 'Pedro')
INSERT INTO @Table VALUES( 1, 'Juan')
INSERT INTO @Table VALUES( 2, 'Pablo')
INSERT INTO @Table VALUES( 3, 'Marcelo')
INSERT INTO @Table VALUES( NULL, 'Leonardo')
INSERT INTO @Table VALUES( 4, 'Ignacio')
-- Get all the collumns by indicating *
SELECT COUNT(*) AS 'AllRowsCount'
FROM @Table
-- Get only content columns ( exluce NULLs )
SELECT COUNT(CustomerId) AS 'OnlyNotNullCounts'
FROM @Table
Нет никакой разницы, если один столбец исправлен в вашей таблице, если вы хотите использовать более одного столбца, чем вы должны указать, сколько столбцов вам нужно подсчитать ...
Спасибо,
В основном функция COUNT(*) возвращает все строки из таблицы, тогда как COUNT(COLUMN_NAME) - нет; то есть исключает нулевые значения, на которые все здесь также ответили.
Но самое интересное - это оптимизировать запросы и базу данных. Лучше использовать COUNT(*), если не выполняется несколько подсчетов или сложный запрос, а не COUNT(COLUMN_NAME). В противном случае это действительно снизит производительность вашей БД при работе с огромным количеством данных.
Как упоминалось в предыдущих ответах, Count(*) считает даже столбцы NULL, тогда как count(Columnname) считает, только если столбец имеет значения.
Всегда лучше избегать * (Select *, count *,…)
Избегать COUNT(*) - не лучшая практика.
COUNT(*) - возвращает общее количество записей в таблице (включая записи с нулевым значением).
COUNT(Column Name) - возвращает общее количество записей, отличных от NULL. Это означает, что он игнорирует подсчет записей со значением NULL в этом конкретном столбце.
Просто любопытно: если у вас есть строка с все NULL, будет ли count (*) по-прежнему считать ее или просто count (столбец) для всех столбцов?