数据库查询相信很多人都不陌生,所有经常有人调侃程序员就是CRUD专员,这所谓的CRUD指的就是数据库的增删改查。
在数据库的增删改查操作中,使用最频繁的就是查询操作。而在所有查询操作中,统计数量操作更是经常被用到。
关于数据库中行数统计,无论是MySQL还是Oracle,都有一个函数可以使用,那就是COUNT。
但是,就是这个常用的COUNT函数,却暗藏着很多玄机,尤其是在面试的时候,一不小心就会被虐。不信的话请尝试回答下以下问题:
1、COUNT有几种用法?
2、COUNT(字段名)和COUNT(*)的查询结果有什么不同?
3、COUNT(1)和COUNT(*)之间有什么不同?
4、COUNT(1)和COUNT(*)之间的效率哪个更高?
5、为什么《阿里巴巴Java开发手册》建议使用COUNT(*)
6、MySQL的MyISAM引擎对COUNT(*)做了哪些优化?
7、MySQL的InnoDB引擎对COUNT(*)做了哪些优化?
8、上面提到的MySQL对COUNT(*)做的优化,有一个关键的前提是什么?
9、SELECT COUNT(*) 的时候,加不加where条件有差别吗?
10、COUNT(*)、COUNT(1)和COUNT(字段名)的执行过程是怎样的?
以上10道题,如果您可以全部准确无误的回答的话,那说明你真的很了解COUNT函数了,如果有哪些知识点是不了解的,那么本文正好可以帮你答疑解惑。
认识COUNT
关于COUNT函数,在MySQL官网中有详细介绍:
简单翻译一下:
1、COUNT(expr) ,返回SELECT语句检索的行中expr的值不为NULL的数量。结果是一个BIGINT值。
2、如果查询结果没有命中任何记录,则返回0
3、但是,值得注意的是,
COUNT(*)
的统计结果中,会包含值为NULL的行数。
即以下表记录
create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)
复制代码
使用语句count(*),count(id),count(id2)查询结果如下:
select count(*),count(id),count(id2)
from #bla
results 7 3 2
复制代码
除了
COUNT(id)
和
COUNT(*)
以外,还可以使用
COUNT(常量)
(如
COUNT(1)
)来统计行数,那么这三条SQL语句有什么区别呢?到底哪种效率更高呢?为什么《阿里巴巴Java开发手册》中强制要求不让使用
COUNT(列名)
或
COUNT(常量)
来替代
COUNT(*)
呢?
COUNT(列名)、COUNT(常量)和COUNT(*)之间的区别
前面我们提到过
COUNT(expr)
用于做行数统计,统计的是expr不为NULL的行数,那么
COUNT(列名)
、
COUNT(常量)
和
COUNT(*)
这三种语法中,expr分别是
列名
、
常量
和
*
。
那么
列名
、
常量
和
*
这三个条件中,
常量
是一个固定值,肯定不为NULL。
*
可以理解为查询整行,所以肯定也不为NULL,那么就只有
列名
的查询结果有可能是NULL了。
所以,
COUNT(常量)
和
COUNT(*)
表示的是直接查询符合条件的数据库表的行数。而
COUNT(列名)
表示的是查询符合条件的列的值不为NULL的行数。
除了查询得到结果集有区别之外,
COUNT(*)
相比
COUNT(常量)
和
COUNT(列名)
来讲,
COUNT(*)是SQL92定义的标准统计行数的语法,因为他是标准语法,所以MySQL数据库对他进行过很多优化。