在上周的“在 MySQL 中获取行计数”文章中,我们采用了原生的 COUNT() 函数的不同变体来计算一个 MySQL 表中的行数。在今天的后续文章中,我们将以更复杂的方式使用 COUNT() 函数来计算唯一值以及满足条件的值。
计算非重复项
COUNT(DISTINCT) 函数返回具有唯一非 NULL 值的行数。因此,包含 DISTINCT 关键字可以消除计数中的重复行。它的语法是:
COUNT(DISTINCT expr,[expr...])与正则 COUNT() 函数一样,上面的 expr 参数可以是任何给定的表达式,包括指定的列、所有列(*)、函数返回值或表达式(如 IF/CASE 语句)。
简单的例子
假设我们有以下 clients 表:
+------------+-------------+| last_name | first_name |
+------------+-------------+
| Tannen | Biff |
+------------+-------------+
| McFly | Marty |
+------------+-------------+
| Brown | Dr. Emmett |
+------------+-------------+
| McFly | George |
+------------+-------------+
调用 COUNT(*) 将返回所有行的数量(4),而在 last_name 上使用 COUNT DISTINCT 将计算重复姓氏的行为 1,这样我们得到总数 3:
SELECT COUNT(*), COUNT(DISTINCT last_name) FROM clients;+----------+---------------------------+
| COUNT(*) | COUNT(DISTINCT last_name) |
+----------+---------------------------+
| 4 | 3 |
+----------+---------------------------+
使用表达式的条件性计数
如上所述,COUNT() 函数参数不限于列名,也可以是函数返回值和表达式(如 IF/CASE 语句)。
这是一个包含多个用户的电话号码和性别的表(为简单起见只有两列):
+------------+---------+| tel | sex |
+------------+---------+
| 7136609221 | male |
+------------+---------+
| 7136609222 | male |
+------------+---------+
| 7136609223 | female |
+------------+---------+
| 7136609228 | male |
+------------+---------+
| 7136609222 | male |
+------------+---------+
| 7136609223 | female |
+------------+---------+
假设我们想要建立一个查询,让我们知道表中有多少不同的女性和男性。用户是通过他们的电话号码(tel)识别。同一个“tel”可能会出现多次,但 tel 的性别应该只计算一次。
这是为每列使用单独的 COUNT DISTINCT 的一个选项:
SELECT COUNT(DISTINCT tel) gender_count,COUNT(DISTINCT CASE WHEN gender = 'male' THEN tel END) male_count,
COUNT(DISTINCT CASE WHEN gender = 'female' THEN tel END) female_count
FROM people
这个 SELECT 语句将产生以下结果:
+--------------+------------+---------------+| gender_count | male_count | female_count |
+--------------+------------+---------------+
| 4 | 3 | 1 |
+--------------+------------+---------------+
额外提示-分组并包括总计
你还可以使用 GROUP BY 垂直堆叠计数:
+---------+-------+| GroupId | Count |
+---------+-------+
| 1 | 5 |
+---------+-------+
| 2 | 4 |
+---------+-------+
| 3 | 7 |
+---------+-------+
| Total: | 11 |
+---------+-------+
“Total:”是使用 SQL GROUPING() 函数生成的,该函数已在 MySQL 8.0.1 中添加。它将表示超级聚合行(由 ROLLUP 生成)中所有的值的集合的 NULL 与正则行中的NULL 区分起来。
这是完整的 SQL:
Select Case When Grouping(GroupId) = 1Then 'Total:'
Else GroupId
End As GroupId,
Count(*) Count
From user_groups
Group By GroupId With Rollup
Order By Grouping(GroupId), GroupId
下周,我们将从多个表和视图中获取行计数。