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

Posted

技术标签:

【中文标题】是否可以在 Count() 中指定条件?【英文标题】:Is it possible to specify condition in Count()? 【发布时间】:2010-11-26 20:53:26 【问题描述】:

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

我想在count语句中做,不使用WHERE;我之所以问这个问题是因为我需要在同一个 SELECT 中计算 Managers 和 Other (类似于 Count(Position = Manager), Count(Position = Other)) 所以 WHERE 在这个例子中对我没有用处。

【问题讨论】:

嘘所有 * 用户,使用 Count(SomeColumnInYourTable) where Position = 'Manager' @Mark:在所有现代数据库中,这并没有任何不同。 @Mark & Philippe:实际上它可以产生很大的不同。如果字段可以为空且没有索引,则查询需要触及表中的每条记录,因此使用 count(*) 和 count(field) 可以获得不同的结果和不同的性能。 多年来,我已经分析了 count(*) 与 count(x) 的执行计划,但到目前为止,我还没有找到一个显示性能差异的执行计划。这就是为什么我真的很想看到一个存在差异的查询示例。 @Matthew:我们说的不是SELECT *,而是SELECT COUNT(*),这是一个完全不同的野兽。 【参考方案1】:

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

【讨论】:

如果我的字段是整数并且我想匹配空值怎么办。它不能以这种方式工作 select count(case IntegerField when 'NULL' then 1 else null end) from @Faizan null 很特别。使用case when IntegerField is null then ... 处理布尔字段时,您可以使用:SUM(CONVERT(int, IsManager)) SQL Server 暗示else null 用于case 语句,因此count() 示例可以短10 个字符(如果算上空格)。【参考方案2】:

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

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 ...

【讨论】:

@RedFilter 甚至不需要指定else 部分,只需在1 之后指定end @Denis:正确 - 我经常留下else,因为它可以更好地记录案例语句的结果,尤其是对于新手 SQL 开发人员。为简洁起见,在这种情况下可以将其删除。【参考方案3】:

@Guffa 的回答非常好,只需指出使用 IF 语句可能更简洁

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

【讨论】:

我用过这个,不过应该是IIF,不是IF。 :) database.guide/sql-server-if-vs-iif-whats-the-difference @Brian MacKay,你是对的,我在考虑 mysql ^^¡,答案已编辑。【参考方案4】:

取决于您的意思,但该含义的另一种解释是您希望计算具有特定值的行,但不想将 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

【讨论】:

【参考方案5】:

如果使用 Postgres 或 SQLite,可以使用 Filter 子句来提高可读性:

SELECT
  COUNT(1) FILTER (WHERE POSITION = 'Manager') AS ManagerCount,
  COUNT(1) FILTER (WHERE POSITION = 'Other') AS OtherCount
FROM ...

BigQuery 还具有 Countif - 在此处查看不同 SQL 方言对这些功能的支持: https://modern-sql.com/feature/filter

【讨论】:

【参考方案6】:

如果您使用的是 SQL 2005 或更高版本,您也可以使用 Pivot 关键字

more info 和来自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')

【讨论】:

【参考方案7】:

你的意思是这样吗:

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

如果是这样,那就行了!

【讨论】:

编辑显示他不想用 WHERE 子句限制行【参考方案8】:

我知道这已经很老了,但我喜欢 NULLIF 用于此类场景的技巧,到目前为止我没有发现任何缺点。看看我的copy&pasteable例子,虽然不是很实用,但演示了如何使用它。

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

评论赞赏:-)

【讨论】:

【参考方案9】:
SELECT COUNT(*) FROM bla WHERE Position = 'Manager'

【讨论】:

不,问题明确表示“我想在 count 语句中这样做,而不是使用 WHERE”【参考方案10】:

注意 PrestoDB SQL(来自 Facebook),有一个捷径:

https://prestodb.io/docs/current/functions/aggregate.html

count_if(x) → bigint

返回 TRUE 输入值的数量。这 函数等价于count(CASE WHEN x THEN 1 END)

【讨论】:

【参考方案11】:

这是我为获取一个数据集所做的,该数据集包括每个集装箱内的总数和符合条件的数量。这让我回答了“有多少运输容器中超过 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

【讨论】:

【参考方案12】:

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

【讨论】:

为什么我会投反对票?在我回答之后(或者可能是同一时间),很多人回答了类似的事情,他们没有得到任何反对意见。 /:( 您投了反对票,因为问题是“在计数中指定条件”而不是“按条件计算值”。所以你回答错了问题 对答案投反对票有点不公平,当答案写出来时,它是问题的正确解决方案....他在这个答案后 4 分钟添加了额外的文字!

以上是关于是否可以在 Count() 中指定条件?的主要内容,如果未能解决你的问题,请参考以下文章

在 MySQL 的“完全外连接”中指定条件的目的是啥?

如何使用多个条件查找查询在 MongoDB 中指定字段?

在不允许新建对象的条件下,将list中指定条件的值去除

如果满足另一个中指定的条件,则更新查询在其中一个中更新数据

如何在Laravel中的find()方法中指定两个或更多条件?

R语言-查询向量中指定条件的数据-which