前言

现在大多数开发工作中,已经可以使用一些组件或框架提供的强大的条件构造器来完成查询数据了,虽然强大而且方便,但也还是存在很多业务场景需要实打实的编写传统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查询思维/场景的更多相关文章

  1. WordPress 常用数据库SQL查询语句大全

    在使用WordPress的过程中,我们少不了要对数据库进行修改操作,比如,更换域名.修改附件目录.批量修改文章内容等等.这个时候,使用SQL查询语句可以大大简化我们的工作量. 关于如何操作SQL查询语 ...

  2. 一些常用的SQL查询语句

    学习网站:http://www.w3cschool.cc/sql/sql-tutorial.html 一:查询所有表的属性 SELECT 'ALTER TABLE '+ CASE WHEN O.sch ...

  3. C# SQL查询结果ToDataTable

    作者:卞功鑫 转载请保留:http://www.cnblogs.com/BinBinGo/p/6400944.html 最最常用的SQL 查询的返回结果,插入到DataTable 中 //1 连接字符 ...

  4. Oracle常用SQL查询(2)

    三.查看数据库的SQL 1 .查看表空间的名称及大小 select  t.tablespace_name,  round ( sum (bytes / ( 1024 * 1024 )), 0 ) ts ...

  5. Oracle常用SQL查询

    一.ORACLE的启动和关闭 1.在单机环境下要想启动或关闭oracle系统必须首先切换到oracle用户,如下: su - oracle a.启动Oracle系统 oracle>svrmgrl ...

  6. ORACLE 常用SQL查询

    一.ORACLE的启动和关闭 1 .在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su  -  oracle a.启动ORACLE系统 oracle > sv ...

  7. Mysql常用30种SQL查询语句优化方法

    出处:http://www.antscode.com/article/12deee70111da0c4.html 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使 ...

  8. MySQL 常用30种SQL查询语句优化方法

    1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...

  9. 笔面试复习(spring常用.jar包/事务/控制反转/bean对象管理和创建/springMVC工作原理/sql查询)

    ###spring常用jar包1.spring.jar是包含有完整发布模块的单个jar包.2.org.springframework.aop包含在应用中使用Spring的AOP特性时所需要的类.3.o ...

随机推荐

  1. go语言内存对齐

    内存对齐 为保证程序顺利高效的运行,编译器会把各种类型的数据安排到合适的地址并占用合适的长度,这就是内存对齐 每种类型的对齐值就是他的内存边界 64位 类型 对齐边界 (对齐值) int8 1byte ...

  2. MySQL高可用主从复制新增slave

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 基础环境 二 新增slave2方案 2.1 方案1:-复制主库 2.2 方案2 ...

  3. android activity pass data to accessibilityservice 数据传递

    不同类型的 service 传递数据的方式不同,accessibilityservice 运行在独立进程,且被系统接管,比较特别 在 AccessibilityService 的 onCreate 内 ...

  4. springMVC学习总结(三) --springMVC重定向

    根据springMVC学习总结(一) --springMVC搭建搭建项目 在com.myl.controller包下创建一个java类WebController. 在jsp子文件夹下创建一个视图文件i ...

  5. JS_DOM操作之查找标签

    1 - 直接查找标签 // 方式1:获取元素 document.getElementsByTagName("标签名") document.getElementById(" ...

  6. client-go实战之五:DiscoveryClient

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. SpringBoot异步使用@Async原理及线程池配置

    前言 在实际项目开发中很多业务场景需要使用异步去完成,比如消息通知,日志记录,等非常常用的都可以通过异步去执行,提高效率,那么在Spring框架中应该如何去使用异步呢 使用步骤 完成异步操作一般有两种 ...

  8. JAVA安全基础之代理模式(一)

    JAVA安全基础之代理模式(一) 代理模式是java的一种很常用的设计模式,理解代理模式,在我们进行java代码审计时候是非常有帮助的. 静态代理 代理,或者称为 Proxy ,简单理解就是事情我不用 ...

  9. 制作nginx+php的docker镜像方法

    制作nginx+php的docker镜像方法一.准备安装的工具工具:docker-17.06.0-ce.nginx-1.13.2.PHP-5.5.38 .supervisor配置思路:1.安装dock ...

  10. 为什么不推荐Python初学者直接看项目源码

    无论是有没有其他语言的经验,入门Python都很简单.Python拥有简单直观的语法,方便的语法糖,以及丰富的第三方库.只要一个基础的Python教程,大家基本上都能无障碍的入门.在入门之后,很多人对 ...