SQL 语句复习一
# 建表语句(注意建表语句的自增长从 8 开始)
CREATE TABLE `student` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `name` VARCHAR(30) DEFAULT NULL, `sex` TINYINT(1) DEFAULT '0', `score` INT(10) NOT NULL, `dept` VARCHAR(10) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MYISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
# 数据的初始化
INSERT INTO student (NAME,sex,score,dept) VALUES("a","1",90,"dev");
INSERT INTO student (NAME,sex,score,dept) VALUES("b","1",90,"dev");
INSERT INTO student (NAME,sex,score,dept) VALUES("b","0",88,"design");
INSERT INTO student (NAME,sex,score,dept) VALUES("c","0",60,"sales");
INSERT INTO student (NAME,sex,score,dept) VALUES("c","0",89,"sales");
INSERT INTO student (NAME,sex,score,dept) VALUES("d","1",100,"product");
# 接下来是实战
# 找出每个部门分数最高的
SELECT
id,NAME,MAX(score),sex,dept
FROM
student
GROUP BY dept
说明:使用 group by 后面跟的字段一定要出现在 select 关键字的后面,要不然别人都不知道你是怎么分组的,查询出来的结果集会很怪。
这只是个简单的例子,我们可以再把这个例子复杂化,比如分数最高的必须是女生,即 sex 列值必须为 0 才挑选出,这时我第 1 次写的 sql 语句是:
注意:这里应该指出,where 关键字 不能出现在 group by 关键字的后面。
正确的 SQL 语句应该为:
SELECT id,NAME,MAX(score),sex,dept FROM student GROUP BY dept HAVING sex = '0'
查询出的结果集:
这里我们没有用 where 语句而是用了 having 子句,这里简单说明一下,因为我们的条件是在分组后进行的。其实分组前挑选出sex=’0’,然后再按照dept部门分组,也是可行的。具体可以根据笔试题的具体要求来定。
SELECT id,NAME,MAX(score),sex,dept FROM student WHERE sex = '0' GROUP BY dept
我们发现查询出的结果是一致的,如果把筛选的条件改为必须部门所有人的分数之和大于 150 才能把分数最高的部门的人列出来。这里就必须使用 having 了,因为 having 里面可以使用聚合函数 sum ,并且也必须分完组我们才能得到这个组的总分数,才能比较是否该值大于150:
我们来观察这条 SQL 语句的特点:
- having 是在分组之后进行筛选的,所以 SQL 的执行顺序应该是:先分组,再 select ,再 having;
- 所以 having 子句里面可以使用别名;
- 只要使用了聚合函数,除了分组字段必须出现以外,其它 select 后面的字段也必须使用聚合函数,要不然你的结果集看过去会怪怪的。
对于 group by 子句,还有很多话题要说。希望自己能多查询一些资料,加深体会。
额外增加一个例子,比如我要选出不重复的部门,我们可以使用
SELECT DISTINCT dept FROM student;
但是如果我们还要列出它的 id 等一些其他信息,我们如果这样:
这是不行的,因为 distinct 只能放到开始位置,如果:
SELECT DISTINCT dept,NAME FROM student GROUP BY dept;
注意:此时 name 的值不具有参考意义。
按照dept分组,自然就达到去重的目的了。所以有时候如果我们碰到了一个问题很难解决,比如用distinct去重,并带上其他列值,我们就需要尝试换个思路,可能答案自然就找到了。