一个很有趣的问题,我现在有一张products
表,表中数据如下:
[为了简洁,截去了prod_desc
的描述信息]
现在我执行:
select vend_id, prod_price from products where prod_price >= 10;
结果如下:
没有问题,然后我们执行:
select vend_id, count(*) as num_prods, prod_price from products where prod_price >= 10;
是不是很奇怪?前面的id
为1003
, 1005
的家伙哪里去了?为什么结果会是这种情况?
还有,如果执行:
select * from products group by vend_id;
[为了简洁,截去了prod_desc
的描述信息]
可以和前面的select * from products
比较 一下。你又是否感到奇怪呢?
其实并不奇怪,奇怪的应该是Mysql
,上面的句子应该报错的,事实上它没有!
在《数据库系统概念》这本书中用如下的表述:
当SQL查询使用分组时,一个很重要的事情是需要保证出现在select语句中但是没有被聚集的属性只能是出现在group by子句中的那些属性,换句话说,任何没有出现在group by子句中的属性如果出现在select子句中的话,那么该属性只能出现在聚集函数的内部,否则,这样的查询就是错误的。
我们回过头来看看select * from products group by vend_id;
查询,很明显,这个查询按照vend_id
分组,然而select
子句中的代表products
中的所有属性,更进一步的,除了vend_id
之外,该表的其他属性都未出现在group by
子句中,也没有出现在聚集函数的内部(所谓聚集函数是指sum
,max
,count
等这些函数),因此,这个语句是错误的,实际上,结果也很让我们困惑。
我们更进一步地查看上一个令人困惑的结果,它对应的语句是:
select vend_id, count(*) as num_prods, prod_price from products where prod_price >= 10;
这个语句其实也是错误的,虽然这里并没有group by
语句,但是看看前面所说的:
任何没有出现在group by子句中的属性如果出现在select子句中的话,那么该属性只能出现在聚集函数的内部,否则,这样的查询就是错误的。
其实vend_id
,prod_price
这些属性都没有出现在group by
子句中吧,但是它们出现在了select
子句中,所以错误。
类似的例子还有很多,比如下面是一个正确的写法:
select vend_id, prod_price from products where prod_price >= 10;
我们这么写:
select vend_id,sum(prod_price) from products where prod_price >= 10;
这么写:
select vend_id,count(prod_price) from products where prod_price >= 10;
都是错的!
别把聚集函数和普通属性搅和在一起,因为Mysql并不报错,最终的结果会使你万分困惑!