是否可以在Count()中指定条件?


391

是否可以在中指定条件Count()?我只想计算“位置”列中具有“管理器”的行。

我想在count语句中执行此操作,而不要使用WHERE; 我问这个问题,因为我需要计算两个经理和其他在同一个SELECT(像Count(Position = Manager), Count(Position = Other))这样WHERE在这个例子中没有用我。


4
嘘所有*的用户,使用次数(SomeColumnInYourTable),其中位置=“经理”
马克·迪金森

6
@Mark:在所有现代数据库上,这没有任何区别。
菲利普·莱巴特

4
@Mark&Philippe:实际上,它可以带来很大的不同。如果该字段可为空且未索引,则查询需要触摸表中的每条记录,因此使用count(*)和count(field)可以得出不同的net结果和不同的性能。
Guffa

3
我已经分析了count(*)vs count(x)的执行计划多年了,到目前为止,我还没有找到一个表现出性能差异的计划。这就是为什么我真的很想看看有区别的查询示例。
菲利普·莱伯特

2
@Matthew:我们不是在谈论SELECT *,而是SELECT COUNT(*),这是完全不同的野兽。
菲利普·莱伯特

Answers:


663

如果您不能只使用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 ...

如果我的字段是整数并且我想匹配null怎么办。它无法通过这种方式工作,从
Faizan'Faizan '16

2
@Faizan null很特别。用途case when IntegerField is null then ...
Peet Brits

使用布尔字段时,可以使用以下命令:SUM(CONVERT(int, IsManager))
Simon_Weaver

2
SQL Server包含一个else nullfor case语句,因此该count()示例可以短10个字符(如果计算空格)。
Michael-Clay Shirky在哪里,

212

假设您也不想因为聚合其他值而限制返回的行,则可以这样操作:

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

假设在同一列中您具有经理,主管和团队负责人的值,您可以像这样获得每个值:

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部分,只需end1。之后。
Denis Valeev 2010年

7
@Denis:正确-我经常留在其中else,因为它可以更好地记录case语句的结果,尤其是对于novie SQL开发人员而言。为简便起见,在这种情况下可以将其删除。
RedFilter 2010年

30

@Guffa的答案非常好,只需指出,使用IF语句可能会更干净

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

21

取决于您的意思,但含义的另一种解释是您要对具有特定值的行进行计数,但又不想将仅限SELECT于这些行...

您可以使用SUM()in子句来完成此操作,而不是使用COUNT():eg

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

如果您使用的是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
SELECT COUNT(*) FROM bla WHERE Position = 'Manager'

2

我认为您可以使用简单的WHERE子句来仅选择对某些记录的计数。


为什么我要投反对票?在我回答(或可能是同一时间)之后,许多人回答了类似的事情,但他们没有得到任何反对。/ :(
NawaMan

4
由于问题是“在Count中指定条件”而不是“按条件计数值”,因此您会感到不满。所以您回答的是错误的问题
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 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.