在平时的开发中很少用到“GROUP BY”和“HAVING”语句,几乎忽略了sql语句中还有这样的分组和筛选功能,这几天为学生选课所累,幸好关键时刻想到了这两个语句,帮了大忙。
因为疏忽,上次选课时将“生理与健康”、“心理学与生活”课程归到了“艺术”类,教务处也没有通知更改,结果这次选课时有些学生就有意见了:老师,我选了“生理与健康”,这次艺术类的课程就不能选了,怎么办?因为学校为避免学生过早偏科,促进学生的全面发展,规定同一类课程只能选修一门。
怎么办,只能纠正,仅仅修改课程的归类那是很方便的,问题是这些学习了“生理与健康”、“心理学与生活”课程的学生又选择了“体育健康”类的课程。必须要把这些学生的选课记录找出,然后退选,补选时通知他们重新选择。
但是在1400多条记录中用肉眼观察实在是笨得可怜的做法,并有点像大海捞针。拍拍脑袋,终于想到了“GROUP BY”和“HAVING”语句,写出以下sql语句,顺利找出了两次都选择“体育健康”类的课程的学生,特此记录,并自我祝贺在数据库方面有了新的提高。
SELECT * FROM result
WHERE sid IN
(SELECT sid FROM result where c_sclassid=4 GROUP BY sid HAVING COUNT(*) >1)
order by sid desc
小资料:
GROUP BY 子句包含以下组件:
一个或多个自由聚合的表达式。通常是对分组列的引用。
ALL 关键字(可选),该关键字指定返回由 GROUP BY 子句产生的所有组,即使某些组没有符合搜索条件的行。
CUBE 或 ROLLUP。
通常情况下,HAVING 子句与 GROUP BY 子句一起使用,不过也可以单独指定 HAVING 子句。
只要表达式中不包括聚合函数,就可通过该表达式分组,例如:
SELECT DATEPART(yy, HireDate) AS Year,
COUNT(*) AS NumberOfHires
FROM Northwind.dbo.Employees
GROUP BY DATEPART(yy, HireDate)
下面是结果集。
Year NumberOfHires
1992 3
1993 3
1994 3
(3 row(s) affected)
在 GROUP BY 子句中,必须指定表或视图列的名称,而不是使用 AS 子句指派的结果集列的名称。例如,以 GROUP BY Year 替换 GROUP BY DATEPART(yy, HireDate) 子句是不合法的。
可以在 GROUP BY 子句中列出多个列以嵌套组,即可以通过列的任意组合分组表。例如,以下查询按类型和出版商 ID 分组,得到平均价格和 year-to-date 的销售额总和:
USE pubs
SELECT type, pub_id, ’avg’ = AVG(price), ’sum’ = sum(ytd_sales)
FROM titles
GROUP BY type, pub_id
下面是结果集:
type pub_id avg sum
------------ ------ ---------------------- -----------
business 0736 2.99 18722
psychology 0736 11.48 9564
mod_cook 0877 11.49 24278
psychology 0877 21.59 375
trad_cook 0877 15.96 19566
UNDECIDED 0877 NULL NULL
business 1389 17.31 12066
popular_comp 1389 21.48 12875
(8 row(s) affected)
SQL语言中设定集合函数的查询条件时使用HAVING从句而不是WHERE从句。通常情况下,HAVING从句被放置在SQL命令的结尾处。