Navicat 博客

2018 年 4 月 4 日,由 Robert Gravelle 撰写

在上周的“在 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) = 1
             Then 'Total:'
             Else GroupId
        End As GroupId,
        Count(*) Count
From    user_groups
Group By GroupId With Rollup
Order By Grouping(GroupId), GroupId

下周,我们将从多个表和视图中获取行计数。

Navicat 文章
频道条目
分享
文章归档