来谈谈MySQL的聚合函数COUNT

前言

对于常常使用MySQL的同学,对于聚合函数count()肯定是不陌生的了,今天我们通过表自连接排序来谈谈count()函数的作用。

背景补充

count()函数是用来统计表中记录的一个函数,返回匹配条件的行数。

count()语法:

  1. count(*)—-包括所有列,返回表中的记录数,相当于统计表的行数,在统计结果的时候,不会忽略列值为NULL的记录。
  2. count(1)—-忽略所有列,1表示一个固定值,也可以用count(2)、count(3)代替,在统计结果的时候,不会忽略列值为NULL的记录。
  3. count(列名)—-只包括列名指定列,返回指定列的记录数,在统计结果的时候,会忽略列值为NULL的记录(不包括空字符串和0),即列值为NULL的记录不统计在内。

(4)count(distinct 列名)—-只包括列名指定列,返回指定列的不同值的记录数,在统计结果的时候,在统计结果的时候,会忽略列值为NULL的记录(不包括空字符串和0),即列值为NULL的记录不统计在内。

count(*)&count(1)&count(列名)执行效率比较:

(1)如果列为主键,count(列名)效率优于count(1)

(2)如果列不为主键,count(1)效率优于count(列名)

(3)如果表中存在主键,count(主键列名)效率最优

(4)如果表中只有一列,则count(*)效率最优

(5)如果表有多列,且不存在主键,则count(1)效率优于count(*)

因为count(*)和count(1)统计过程中不会忽略列值为NULL的记录,所以可以通过以下两种方式来统计列值为NULL的记录数:

(1)select count(*) from table where is_active is null;
(2)select count(1) from table where is_active is null;

特例:

(1)select count(‘’) from table;-返回表的记录数
(2)select count(0) from table;-返回表的记录数
(3)select count(null) from table;-返回0

案例

首先我们来查看案例的表数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> select * from invoices;
+------------+-------------+-----------+---------------+---------------+--------------+------------+--------------+
| invoice_id | number | client_id | invoice_total | payment_total | invoice_date | due_date | payment_date |
+------------+-------------+-----------+---------------+---------------+--------------+------------+--------------+
| 1 | 91-953-3396 | 2 | 0.00 | 0.00 | 2019-03-09 | 2019-03-29 | NULL |
| 2 | 03-898-6735 | 5 | 8.18 | 8.18 | 2019-06-11 | 2019-07-01 | 2019-02-16 |
| 3 | 20-228-0335 | 5 | 0.00 | 0.00 | 2019-07-31 | 2019-08-20 | NULL |
| 4 | 56-934-0748 | 3 | 152.21 | 0.00 | 2019-03-08 | 2019-03-28 | NULL |
| 5 | 87-052-3121 | 5 | 0.00 | 0.00 | 2019-07-18 | 2019-08-07 | NULL |
| 6 | 75-587-6626 | 1 | 157.78 | 74.55 | 2019-01-29 | 2019-02-18 | 2019-01-07 |
| 7 | 68-093-9863 | 3 | 133.87 | 0.00 | 2019-09-04 | 2019-09-24 | NULL |
| 8 | 78-145-1093 | 1 | 189.12 | 0.00 | 2019-05-20 | 2019-06-09 | NULL |
| 9 | 77-593-0081 | 5 | 0.00 | 0.00 | 2019-07-09 | 2019-07-29 | NULL |
| 10 | 48-266-1517 | 1 | 159.50 | 0.00 | 2019-06-30 | 2019-07-20 | NULL |
| 11 | 20-848-0181 | 3 | 126.15 | 0.03 | 2019-01-07 | 2019-01-27 | 2019-01-15 |
| 13 | 41-666-1035 | 5 | 87.44 | 87.44 | 2019-06-25 | 2019-07-15 | 2019-01-30 |
| 15 | 55-105-9605 | 3 | 167.29 | 80.31 | 2019-11-25 | 2019-12-15 | 2019-01-19 |
| 16 | 10-451-8824 | 1 | 162.02 | 0.00 | 2019-03-30 | 2019-04-19 | NULL |
| 17 | 33-615-4694 | 3 | 126.38 | 68.10 | 2019-07-30 | 2019-08-19 | 2019-01-19 |
| 18 | 52-269-9803 | 5 | 42.77 | 42.77 | 2019-05-23 | 2019-06-12 | 2019-01-12 |
| 19 | 83-559-4105 | 1 | 134.47 | 0.00 | 2019-11-23 | 2019-12-13 | NULL |
+------------+-------------+-----------+---------------+---------------+--------------+------------+--------------+
17 rows in set (0.00 sec)

今天我们将利用自左连接排序的案例来探讨count()函数,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
USE sql_invoicing;
-- 1.
select
i.invoice_id,
sum(i2.invoice_total) as R
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;
-- 2.
select
i.invoice_id,
count(1) as R -- 1改成2、3、4、5...结果都是一样,count()代表的是一个固定的值
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;
-- 3.
select
i.invoice_id,
count(i2.invoice_total) as R
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;
-- 4.
select
i.invoice_id,
count(*) as R
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;
-- 5.
select
i.invoice_id,
count('') as R
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;
-- 6.
select
i.invoice_id,
count(NULL) as R
from invoices i
left join invoices i2
on i.invoice_total < i2.invoice_total
group by i.invoice_id
ORDER BY R;

我们拿结果1的返回结果集作为对照,结果集1的第一行是因为没有记录比它大,所以它sum聚合结果就是NULL。

可以发现count(1)count(*)count('')返回的结果是一致的,可以得到结论—count()和count(1)统计过程中不会忽略列值为NULL的记录。区别在于,count(1)忽略列,是一个固定值而`count()`是包括所有列的。

对于结果集3,我们可以知道,count(列名)对于不存在的结果(null)会返回一个0,也即忽略了列记录位NULL的情况,适合用于排序。

对于结果集6,我们可以知道count(NULL)返回的都是0。

参考链接

https://www.cnblogs.com/-flq/p/10302965.html