SQL复杂查询
前言
前面的一篇文章写了下数据库设计和SQL语句基础,里面都是简单的增删改查,而且对最重要的查(Retrieve)也没有深入研究,实在是罪过,那么本文就sql复杂的查询语句进行探讨,也是当作一个记录好了
18.1.9更新:
推荐一本书:SQL学习指南,之前那篇文章还是不太全面,而且更多也只是停留在独立相对没有那么复杂的SQL上,而这一本则是更加全面地SQL扫盲,并且教你如何组合你的SQL
Example I
假设我们现在有张这样的成绩表grade
name | class | score |
---|---|---|
光头 | 语文 | 9 |
吴克 | 语文 | 100 |
光头 | 物理 | 99 |
吴克 | 物理 | 7 |
光头 | 体育 | 100 |
吴克 | 体育 | 5 |
Question:
求不及格(score<60)科目大于等于2门的那个人的平均分,一条sql解决?
Answer:
SELECT name,AVG(score)
FROM grade
WHERE name IN (SELECT name FROM grade WHERE score<60 GROUP BY name HAVING COUNT(score)>=2)
GROUP BY name;
现在我们来一点点理解Answer:
- 1 首先要知道sql执行顺序是:
FROM
(JOIN...ON
)=>WHERE(IN)
=>GROUP BY
=>HAVING
=>WINDOW FUNCTION
=>SELECT
=>DISTINCT
=>UNION(ALL)/INTERSECT/EXCEPT
=>ORDER BY
=>OFFSET
=>LIMIT/FETCH/TOP
REF:Beginner’s Guide to the True Order of SQL Operations
- 2
FROM grade
:
name | class | score |
---|---|---|
光头 | 语文 | 9 |
吴克 | 语文 | 100 |
光头 | 物理 | 99 |
吴克 | 物理 | 7 |
光头 | 体育 | 100 |
吴克 | 体育 | 5 |
- 3
WHERE name IN (SELECT name FROM grade WHERE score<60 GROUP BY name HAVING COUNT(score)>=2)
- 先搞括号内
- 3-1
FROM score
,我们可以得到原来的表如下
name class score 光头 语文 9 吴克 语文 100 光头 物理 99 吴克 物理 7 光头 体育 100 吴克 体育 5 - 3-2
WHERE score<60
,我们可以筛出得分小于60的项的表,如下
name class score 光头 语文 9 吴克 物理 7 吴克 体育 5 - 3-3
GROUP BY name
,相同姓名归一组。GROUP BY简单来说是建立组
注意:截图中sn为name,cn为class,sc为score,下同
- 3-4
HAVING COUNT(score)>=2
,HAVING的作用和WHERE很像都是筛选,不过WHERE不能带聚合函数的(比如SVG,SUM,COUNT等等),HAVING是用来筛选组的,所以往往和GROUP BY配合出现
- 3-5
SELECT name
,根据上面HAVING筛选结果自然就只有吴克
了 - 再搞括号外的
- 3-6
WHERE name IN (吴克)
,故name的取值只能是吴克
,最后得到:
name class score 吴克 语文 100 吴克 物理 7 吴克 体育 5 -
4
GROUP BY name
- 5 最后
SELECT name,AVG(score)
,我们就可以求得我们这位挂课数目在2门以上的这位吴克
同学的平均分了
name | AVG(score) |
---|---|
吴克 | 37.3333 |
Reference:
[1]十步完全理解 SQL
[2]可以这样去理解group by和聚合函数