常用的SQL查询思维/场景
前言
现在大多数开发工作中,已经可以使用一些组件或框架提供的强大的条件构造器来完成查询数据了,虽然强大而且方便,但也还是存在很多业务场景需要实打实的编写传统SQL语句。特别一些测试、维护、问题排查的时候,甚至有的时候系统没有功能,但是又需要某些数据报表,无疑得直接上SQL查询处理。
作为一名开发人员,即使有了便捷的工具可以在开发中直接使用,但是该有的知识技能不应该被遗忘,有的知识技能平时用的不多,但是往往能解决某些核心的重要的问题,这估计就是大多企业招聘面试谈造飞机,实际工作拧螺丝的原因吧,也就是虽然有的东西用的不多,但是必须得备得有,以备关键的时候能处理问题。
快捷工具用多了,基本的底层是会忘记的,今天就来回顾一些常见的查询业务,主要是要理解其中的思维方式。
环境
用于测试的表结构和数据:

DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`cid` int(0) NULL DEFAULT NULL,
`cname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`tid` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES (1, '语文', 1);
INSERT INTO `course` VALUES (2, '数学', 2);
INSERT INTO `course` VALUES (3, '英语', 3);
INSERT INTO `course` VALUES (4, '物理', 4); -- ----------------------------
-- Table structure for sc
-- ----------------------------
DROP TABLE IF EXISTS `sc`;
CREATE TABLE `sc` (
`sid` int(0) NULL DEFAULT NULL,
`cid` int(0) NULL DEFAULT NULL,
`score` int(0) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of sc
-- ----------------------------
INSERT INTO `sc` VALUES (1, 1, 56);
INSERT INTO `sc` VALUES (1, 2, 78);
INSERT INTO `sc` VALUES (1, 3, 67);
INSERT INTO `sc` VALUES (1, 4, 58);
INSERT INTO `sc` VALUES (2, 1, 79);
INSERT INTO `sc` VALUES (2, 2, 81);
INSERT INTO `sc` VALUES (2, 3, 92);
INSERT INTO `sc` VALUES (2, 4, 68);
INSERT INTO `sc` VALUES (3, 1, 91);
INSERT INTO `sc` VALUES (3, 2, 47);
INSERT INTO `sc` VALUES (3, 3, 88);
INSERT INTO `sc` VALUES (3, 4, 56);
INSERT INTO `sc` VALUES (4, 2, 88);
INSERT INTO `sc` VALUES (4, 3, 90);
INSERT INTO `sc` VALUES (4, 4, 93);
INSERT INTO `sc` VALUES (5, 1, 46);
INSERT INTO `sc` VALUES (5, 3, 78);
INSERT INTO `sc` VALUES (5, 4, 53);
INSERT INTO `sc` VALUES (6, 1, 35);
INSERT INTO `sc` VALUES (6, 2, 68);
INSERT INTO `sc` VALUES (6, 4, 71); -- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`sid` int(0) NULL DEFAULT NULL,
`sname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`sage` int(0) NULL DEFAULT NULL,
`ssex` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '刘一', 18, '男');
INSERT INTO `student` VALUES (2, '钱二', 19, '女');
INSERT INTO `student` VALUES (3, '张三', 17, '男');
INSERT INTO `student` VALUES (4, '李四', 18, '女');
INSERT INTO `student` VALUES (5, '王五', 17, '男');
INSERT INTO `student` VALUES (6, '赵六', 19, '女'); -- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
`tid` int(0) NULL DEFAULT NULL,
`tname` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES (1, '叶平');
INSERT INTO `teacher` VALUES (2, '贺高');
INSERT INTO `teacher` VALUES (3, '杨艳');
INSERT INTO `teacher` VALUES (4, '周磊');
预览




查询
--- 查询“001”课程比“002”课程成绩高的所有学生的学号 SELECT t1.sid
FROM
(select sid,score from SC where Cid='001') t1,
(select sid,score from SC where Cid='002') t2
where t1.sid = t2.sid and t1.score > t2.score
-- 查询平均成绩大于60分的同学的学号和平均成绩 SELECT sid, AVG(score)
FROM sc
GROUP BY sid HAVING AVG(score) > 60
-- 查询所有同学的学号、姓名、选课数、总成绩; SELECT st.sid,st.sname,count(sc.cid) as '选课数' ,SUM(sc.score) as '总成绩'
from student st,sc
where st.sid = sc.sid
GROUP BY st.sid,st.sname; -- 或 SELECT st.sid,st.sname,count(sc.cid) as '选课数' ,SUM(sc.score) as '总成绩'
from student st left join sc on st.sid = sc.sid
GROUP BY st.sid,st.sname
-- 查询没学过“叶平”老师课的同学的学号、姓名 select Student.Sid,Student.Sname
from Student
where Sid not in(
SELECT sc.sid
FROM sc
GROUP BY sc.sid,sc.cid HAVING sc.cid in(
SELECT c.cid
FROM course c,teacher t
where c.tid = t.tid AND t.tname = '叶平'
)
) -- 或 select Student.Sid,Student.Sname
from Student
where Sid not in (
select distinct SC.Sid
from SC,Course,Teacher
where SC.Cid=Course.Cid and Teacher.Tid=Course.Tid and Teacher.Tname='叶平');
-- 查询学过“001”并且也学过编号“002”课程的同学的学号、姓名 SELECT student.sid,student.sname
FROM student
WHERE student.sid in(
SELECT a.sid
FROM
(SELECT * from sc WHERE sc.cid = '001') a,
(SELECT * from sc WHERE sc.cid = '002') b
where a.sid = b.sid
) -- 或 select Student.Sid,Student.Sname
from Student,SC
where Student.Sid=SC.Sid and SC.Cid='001'
and exists(
Select *
from SC as SC_2
where SC_2.Sid=SC.Sid and SC_2.Cid='002');
-- 查询学过“叶平”老师所教的所有课的同学的学号、姓名 SELECT st.sid,st.sname
FROM student st
WHERE st.sid in (
SELECT sc.sid
FROM course c,teacher t,sc
where c.cid = sc.cid and t.tid = c.tid and t.tname = '叶平' )
-- 查询课程编号“002”的成绩比课程编号“001”课程低的所有同学的学号、姓名 SELECT st.sid,st.sname
FROM student st where st.sid in(
SELECT a.sid
FROM
( SELECT * from sc where sc.cid = '001' ) a,
( SELECT * from sc where sc.cid = '002' ) b
WHERE a.sid = b.sid AND b.score < a.score
)
-- 查询所有课程成绩小于60分的同学的学号、姓名 select Sid,Sname
from Student
where Sid not in (
select S.Sid from Student AS S,SC where S.Sid=SC.Sid and score>60
);
-- 查询没有学全所有课的同学的学号、姓名SELECT st.sid,st.sname
from student st
where st.sid in (
SELECT sc.sid
FROM sc
GROUP BY sc.sid HAVING count(sc.cid) < (SELECT count(c.cid) FROM course c)
) -- 或 select Student.Sid,Student.Sname
from Student,SC
where Student.Sid=SC.Sid group by Student.Sid,Student.Sname having count(Cid) < (select count(Cid) from Course);
-- 查询至少有一门课与学号为“001”的同学所学相同的同学的学号和姓名; SELECT st.sid,st.sname
FROM student st left join sc on sc.cid in (
SELECT sc.cid
FROM sc
where sc.sid = '001')
GROUP BY st.sid,st.sname
-- “叶平”老师教的课的平均成绩;
SELECT avg(sc.score)
FROM sc
where cid = (
SELECT course.cid from course where course.tid in(
SELECT teacher.tid from teacher where teacher.tname = '叶平'
)
)
-- 查询和“002”号的同学学习的课程完全相同的其他同学学号和姓名
SELECT st.sid,st.sname
from student st
WHERE st.sid in(
SELECT sc.sid
from sc
where sc.cid in (
SELECT sc.cid
from sc
WHERE sc.sid = '002')
GROUP BY sc.sid HAVING count(sc.cid) = ( SELECT count(sc2.cid) from sc sc2 WHERE sc2.sid = '002')
)
-- 平均成绩从高到低显示所有学生的“语文”、“数学”、“英语”三门的课程成绩,按如下形式显示: 学生ID,,数据库,企业管理,英语,有效课程数,有效平均分 SELECT Sid as 学生ID
,(SELECT score FROM SC WHERE SC.Sid=t.Sid AND Cid='001') AS '语文'
,(SELECT score FROM SC WHERE SC.Sid=t.Sid AND Cid='002') AS '数学'
,(SELECT score FROM SC WHERE SC.Sid=t.Sid AND Cid='003') AS '英语'
,COUNT(*) AS 有效课程数, AVG(t.score) AS 平均成绩
FROM SC AS t
GROUP BY Sid
ORDER BY sid
形式 :竖变横

-- 查询各科成绩最高和最低的分:以如下形式显示:课程ID,最高分,最低分
SELECT sc.cid,max(sc.score) as '最高分',min(sc.score) as '最低分'
from sc
GROUP BY sc.cid
ORDER BY sc.cid
-- 查询各科成绩最高和最低的分:以如下形式显示:课程号,课程名,最高分,最低分 SELECT t.cid as '课程号',cname as '课程名',maxsc as '最高分', minsc as '最低分'
from course c RIGHT JOIN (
SELECT sc.cid,max(sc.score) as maxsc, min(sc.score) as minsc
from sc
GROUP BY sc.cid ) t
ON t.cid = c.cid
结语
查询效率:达到一个查询目标,可以有不同的查询方法,当然不同的查询方法也就往往意味着SQL执行的效率不同,在数据量小的时候可能赶紧不明显,但是数据量大的时候就明显了,这意味着我们必须尽量选择高效率的查询方法。
拆解思维:一个复杂的SQL,可以拆解成多个子模块来理解处理。
逆向思维:有时候反着条件查能或者更好的效果,比如上面的查询例子里面的“所有课程成绩都小于60分的同学”时,先把“存在60分以上的课程的同学”这个“补集”查处理,再用not in就可以便捷的达到查询目的。
常用的SQL查询思维/场景的更多相关文章
- WordPress 常用数据库SQL查询语句大全
在使用WordPress的过程中,我们少不了要对数据库进行修改操作,比如,更换域名.修改附件目录.批量修改文章内容等等.这个时候,使用SQL查询语句可以大大简化我们的工作量. 关于如何操作SQL查询语 ...
- 一些常用的SQL查询语句
学习网站:http://www.w3cschool.cc/sql/sql-tutorial.html 一:查询所有表的属性 SELECT 'ALTER TABLE '+ CASE WHEN O.sch ...
- C# SQL查询结果ToDataTable
作者:卞功鑫 转载请保留:http://www.cnblogs.com/BinBinGo/p/6400944.html 最最常用的SQL 查询的返回结果,插入到DataTable 中 //1 连接字符 ...
- Oracle常用SQL查询(2)
三.查看数据库的SQL 1 .查看表空间的名称及大小 select t.tablespace_name, round ( sum (bytes / ( 1024 * 1024 )), 0 ) ts ...
- Oracle常用SQL查询
一.ORACLE的启动和关闭 1.在单机环境下要想启动或关闭oracle系统必须首先切换到oracle用户,如下: su - oracle a.启动Oracle系统 oracle>svrmgrl ...
- ORACLE 常用SQL查询
一.ORACLE的启动和关闭 1 .在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a.启动ORACLE系统 oracle > sv ...
- Mysql常用30种SQL查询语句优化方法
出处:http://www.antscode.com/article/12deee70111da0c4.html 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使 ...
- MySQL 常用30种SQL查询语句优化方法
1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...
- 笔面试复习(spring常用.jar包/事务/控制反转/bean对象管理和创建/springMVC工作原理/sql查询)
###spring常用jar包1.spring.jar是包含有完整发布模块的单个jar包.2.org.springframework.aop包含在应用中使用Spring的AOP特性时所需要的类.3.o ...
随机推荐
- 闭包 panic recover
闭包=函数+外层变量的引用 recover必须搭配defer使用 defer一定要在可能引发panic的语句之前定义
- 移动端ios上下滑动翻页事件失效
移动端开发过程中,在添加上下滑动事件时候,引入了最常用的移动端库zepto.js及其touch模块,有一种现象,安卓的手机没有问题,上下滑动翻页很正常 :但是到了ios上面,好啊,上下滑动会出现弹性滚 ...
- 史上最详细的信号使用说明(已被收藏和N次)
Unix环境高级编程(第三版) 第10章 信号 文章目录 1. 引言 2. 信号的概念 2.1 信号操作之忽略信号 2.2 信号操作之捕捉信号 2.3 信号操作之执行系统默认操作 2.4 常见的信号 ...
- weblogic获取应用目录路径
一.背景说明 在项目开发过程中,本地开发用的windows+tomcat,到了生产中,就成了linux+weblogic.部署工程后,应用报错,显示获取应用目录返回为null. 在网上查阅资料,发现在 ...
- 使用Redis实现分布式会话
1. 概述 传统的单体应用中,用户是否登录,通常是通过从Tomcat容器的session中获取登录用户信息判断的. 但在分布式的应用中,通常负载均衡了多台Tomcat,每台Tomcat都有自己独立的s ...
- 使用 elementUI 的表单进行查询,表单中只有一个文本框时,回车会自动触发表单的提交事件,导致页面的刷新。
使用elementUI的el-form组件进行查询时,当输入框仅有一项时,回车自动提交表单,浏览器会刷新页面: 原因:由于当表单只有一个文本框时,按下回车将会触发表单的提交事件, 从而导致页面刷新. ...
- 关于AS下Gradle安装问题总结
在之前安装AS的随笔中简单描述了解决方法,但不够详细,在第二次创建项目时又遇到了gradle安装错误,通过在网上查找解决方法,发现方法比较多样,且描述不够仔细,本随笔将详细记录我在gradle安装中的 ...
- 学习PDO中的错误与错误处理模式
在 PDO 的学习过程中,我们经常会在使用事务的时候加上 try...catch 来进行事务的回滚操作,但是大家有没有注意到默认情况下 PDO 是如何处理错误语句导致的数据库操作失败问题呢?今天,我们 ...
- js屏蔽右键代码
<script type="text/javascript"> document.body.oncontextmenu=document.body.ondragstar ...
- Jmeter系列(19)- 常用配置文件
JMeter.properties :跟Jmeter配置相关的配置信息都在这边,比如:Jmeter GUI页面的语言.日志级别设置等 User.properties:用户自定义相关的所有变量,会复写J ...