Можно ли указать условие в Count ()?


392

Можно ли указать условие в Count()? Я хотел бы сосчитать только те строки, которые имеют, например, «Менеджер» в столбце «Позиция».

Я хочу сделать это в подсчете, не используя WHERE; Я спрашиваю об этом, потому что мне нужно считать обоих Менеджеров и Других в одном SELECT(что-то вроде Count(Position = Manager), Count(Position = Other))этого WHEREбесполезно для меня в этом примере.


4
Boo для всех пользователей *, используйте Count (SomeColumnInYourTable), где Position = 'Manager'
Марк Дикинсон

6
@Mark: на всех современных базах данных это не имеет никакого значения.
Филипп Лейберт

5
@Mark & ​​Philippe: На самом деле это может иметь большое значение. Если поле обнуляется и не индексируется, запрос должен касаться каждой записи в таблице, поэтому использование count (*) и count (поле) может дать разные результаты и разную производительность.
Гуффа

4
Я анализировал планы выполнения для count (*) и count (x) в течение многих лет, и до сих пор я не нашел ни одного, который показал бы разницу в производительности. Вот почему мне бы очень хотелось увидеть пример запроса, в котором есть разница.
Филипп Лейберт

3
@ Матфея: мы не говорим SELECT *, но SELECT COUNT(*), это совершенно другой зверь.
Филипп Лейберт

Ответы:


664

Если вы не можете просто ограничить сам запрос whereпредложением, вы можете использовать тот факт, что countагрегат учитывает только ненулевые значения:

select count(case Position when 'Manager' then 1 else null end)
from ...

Вы также можете использовать sumагрегат аналогичным образом:

select sum(case Position when 'Manager' then 1 else 0 end)
from ...

Что делать, если мое поле является целым числом, и я хочу, чтобы соответствовать нулю. это не работает таким образом выберите счетчик (случай IntegerField, когда 'NULL', а затем еще 1 нулевой конец) из
Faizan

2
@ Файзан nullособенный. Использованиеcase when IntegerField is null then ...
Пит Бритс

При работе с логическими полями вы можете использовать это:SUM(CONVERT(int, IsManager))
Simon_Weaver

2
SQL Server подразумевает операторы else nullfor case, поэтому count()пример может быть на 10 символов короче (если вы посчитаете пробел).
Майкл - Где Клэй Ширки

213

Предполагая, что вы не хотите ограничивать строки, которые возвращаются, потому что вы также агрегируете другие значения, вы можете сделать это следующим образом:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount
from ...

Допустим, в том же столбце, где у вас были значения Manager, Supervisor и Team Lead, вы можете получить значения для каждого из них следующим образом:

select count(case when Position = 'Manager' then 1 else null end) as ManagerCount,
    count(case when Position = 'Supervisor' then 1 else null end) as SupervisorCount,
    count(case when Position = 'Team Lead' then 1 else null end) as TeamLeadCount,
from ...

3
@RedFilter Нет необходимости указывать elseдеталь, просто endсразу после 1.
Денис Валеев

7
@Denis: правильно - я часто оставляю elsein, так как он лучше документирует результаты оператора case, особенно для начинающих разработчиков SQL. Для краткости его можно удалить в этом случае.
RedFilter

30

Ответ @Guffa отличный, просто отметьте, что, может быть, чище с заявлением IF

select count(IF(Position = 'Manager', 1, NULL)) as ManagerCount
from ...

21

Зависит от того, что вы имеете в виду, но другая интерпретация значения - это то, где вы хотите посчитать строки с определенным значением, но не хотите ограничивать SELECTТОЛЬКО этими строками ...

Вы бы сделали это SUM()с помощью предложения, например, вместо использования COUNT(): например

SELECT SUM(CASE WHEN Position = 'Manager' THEN 1 ELSE 0 END) AS ManagerCount,
    SUM(CASE WHEN Position = 'CEO' THEN 1 ELSE 0 END) AS CEOCount
FROM SomeTable

13

Вы также можете использовать ключевое слово Pivot, если вы используете SQL 2005 или выше

больше информации и от Technet

SELECT *
FROM @Users
PIVOT (
    COUNT(Position)
    FOR Position
    IN (Manager, CEO, Employee)
) as p

Тестовый набор данных

DECLARE @Users TABLE (Position VARCHAR(10))
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('Manager')
INSERT INTO @Users (Position) VALUES('CEO')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')
INSERT INTO @Users (Position) VALUES('Employee')

5

Вы имеете в виду именно это:

SELECT Count(*) FROM YourTable WHERE Position = 'Manager'

Если так, то да, это работает!


1
Редактирование показывает, что он не хочет ограничивать строки с помощью предложения WHERE
KinSlayerUY

4

Я знаю, что это действительно старый, но мне нравится NULLIFхитрость для таких сценариев, и я не нашел никаких минусов до сих пор. Просто посмотрите мой пример копирования и вставки, который не очень практичен, но демонстрирует, как его использовать.

NULLIF может оказать небольшое негативное влияние на производительность, но я думаю, это все равно должно быть быстрее, чем подзапросы.

DECLARE @tbl TABLE ( id [int] NOT NULL, field [varchar](50) NOT NULL)

INSERT INTO @tbl (id, field)
SELECT 1, 'Manager'
UNION SELECT 2, 'Manager'
UNION SELECT 3, 'Customer'
UNION SELECT 4, 'Boss'
UNION SELECT 5, 'Intern'
UNION SELECT 6, 'Customer'
UNION SELECT 7, 'Customer'
UNION SELECT 8, 'Wife'
UNION SELECT 9, 'Son'

SELECT * FROM @tbl

SELECT 
    COUNT(1) AS [total]
    ,COUNT(1) - COUNT(NULLIF([field], 'Manager')) AS [Managers]
    ,COUNT(NULLIF([field], 'Manager')) AS [NotManagers]
    ,(COUNT(1) - COUNT(NULLIF([field], 'Wife'))) + (COUNT(1) - COUNT(NULLIF([field], 'Son'))) AS [Family]
FROM @tbl

Комментарии приветствуются :-)



2

Я думаю, что вы можете использовать простое предложение WHERE, чтобы выбрать только подсчет какой-либо записи.


Почему я получаю отрицательный голос? После того, как я ответил (или, может быть, в то же время), многие люди ответили на аналогичную вещь, и они не получают никакого отрицательного голоса. / :(
NawaMan

4
Вы получаете отрицательный ответ, потому что вопрос «указать условие в подсчете» НЕ «Подсчитать значения по условию». Итак, вы отвечаете не на тот вопрос
Radon8472

3
Немного несправедливо недооценивать ответ, когда ответ был написан, это было правильным решением вопроса ... он добавил дополнительный текст через 4 минуты после этого ответа!
Питер

2

Вот что я сделал, чтобы получить набор данных, который включал в себя как общее количество, так и число, отвечающее критериям, в каждом транспортном контейнере. Это позволило мне ответить на вопрос: «Сколько судоходных контейнеров имеют более чем X% товаров по размеру 51»

select
   Schedule,
   PackageNum,
   COUNT (UniqueID) as Total,
   SUM (
   case
      when
         Size > 51 
      then
         1 
      else
         0 
   end
) as NumOverSize 
from
   Inventory 
where
   customer like '%PEPSI%' 
group by
   Schedule, PackageNum


-4

Используя это, вы получите счет для менеджеров

Select Position, count(*) as 'Position Counter'
from your_table 
group by Position 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.