关于sql:是否可以在Count()中指定条件?

Is it possible to specify condition in Count()?

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

我想在count语句中执行此操作,而不使用WHERE; 我问这个问题是因为我需要在同一SELECT中同时计算Manager和Other(类似于Count(Position = Manager), Count(Position = Other)),因此在本示例中,WHERE对我没有用)。


如果您不能仅使用where子句限制查询本身,则可以使用以下事实:count聚合仅计算非空值:

1
2
SELECT COUNT(CASE POSITION WHEN 'Manager' THEN 1 ELSE NULL END)
FROM ...

您也可以类似的方式使用sum聚合:

1
2
SELECT SUM(CASE POSITION WHEN 'Manager' THEN 1 ELSE 0 END)
FROM ...


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

1
2
SELECT COUNT(CASE WHEN POSITION = 'Manager' THEN 1 ELSE NULL END) AS ManagerCount
FROM ...

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

1
2
3
4
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 ...


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

1
2
SELECT COUNT(IF(POSITION = 'Manager', 1, NULL)) AS ManagerCount
FROM ...

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

您可以使用带有子句的SUM()来执行此操作,而不是使用COUNT()
例如

1
2
3
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

如果您使用的是SQL 2005或更高版本,则也可以使用数据透视关键字

更多信息和来自Technet

1
2
3
4
5
6
7
SELECT *
FROM @Users
PIVOT (
    COUNT(POSITION)
    FOR POSITION
    IN (Manager, CEO, Employee)
) AS p

测试数据集

1
2
3
4
5
6
7
8
9
10
11
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')

我知道这确实很老,但是我喜欢这种情况下的NULLIF技巧,到目前为止我没有发现任何缺点。请看我的可复制粘贴的示例,尽管它不是很实用,但是演示了如何使用它。

NULLIF可能会对性能产生较小的负面影响,但我想它仍然应该比子查询更快。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

评论赞赏:-)


你是说这个意思吗?

1
SELECT COUNT(*) FROM YourTable WHERE POSITION = 'Manager'

如果是这样,那么就可以了!


这是我为获得一个数据集所做的操作,该数据集包含每个运输集装箱中的总数和符合条件的数量。这让我回答了以下问题:"有多少个运输集装箱的X号物品超过51%?"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

请注意,对于PrestoDB SQL(来自Facebook),有一个快捷方式:

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

count_if(x) → bigint

Returns the number of TRUE input values. This
function is equivalent to count(CASE WHEN x THEN 1 END)


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


1
SELECT COUNT(*) FROM bla WHERE POSITION = 'Manager'


使用此功能,您将获得经理的帮助

1
2
3
SELECT POSITION, COUNT(*) AS 'Position Counter'
FROM your_table
GROUP BY POSITION