前言

现在大多数开发工作中,已经可以使用一些组件或框架提供的强大的条件构造器来完成查询数据了,虽然强大而且方便,但也还是存在很多业务场景需要实打实的编写传统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. tensorflow saver简介+Demo with linear-model

    tf.train.Saver提供Save和Restore Tensorflow变量的功能,常用于保存.还原模型训练结果,这在自己的训练和迁移学习中都很有用. 训练.保存脚本: import tenso ...

  2. AbpVnext使用分布式IDistributedCache Redis缓存(自定义扩展方法)

    AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法) 我的依赖包的主要版本以及Redis依赖如下 1:添加依赖 <PackageReferen ...

  3. 【Qt pro 文件配置】

    一.默认配置 默认的pro文件配置如下: 如果采用Qt默认的pro配置,其编译后产生的文件会默认集中分布在debug和release目录下,如下图的obj和moc等文件对后续打包发布并没有意义. 二. ...

  4. Git使用教程五

    基于ssh协议(推荐) 该方式与前面https方式相比,只是影响github对于用户的身份鉴权方式,对于git的具体操作(如提交本地.添加注释.提交远程等操作)没有任何影响.   生成公私钥对指令(需 ...

  5. ubantu上面 NFS服务器安装

    ---恢复内容开始--- N月一更............ 本博客部分参照:https://blog.csdn.net/CSDN_duomaomao/article/details/77822883  ...

  6. 假期作业03:使用IDE开发你的Java程序

    假期作业03:使用IDE开发你的Java程序 一.使用Eclipse创建一个Java项目HelloWorldPrj,编写一个Java程序并运行. 首先要下载eclipse. (注意这里要选一个中国的, ...

  7. LeetCode通关:通过排序一次秒杀五道题,舒服!

    刷题路线参考:https://github.com/chefyuan/algorithm-base 大家好,我是拿输出博客督促自己刷题的老三,前面学习了十大排序:万字长文|十大基本排序,一次搞定!,接 ...

  8. 源码解析.Net中Host主机的构建过程

    前言 本篇文章着重讲一下在.Net中Host主机的构建过程,依旧延续之前文章的思路,着重讲解其源码,如果有不知道有哪些用法的同学可以点击这里,废话不多说,咱们直接进入正题 Host构建过程 下图是我自 ...

  9. IT人计算机网络浅析

    LAN: 局域网 local Area Network WAN: 广域网 Wide Area Network WAN = LAN +LAN+....+LAN 多个LAN 组成 WAN OSI 七层协议 ...

  10. 【Python机器学习实战】决策树与集成学习(七)——集成学习(5)XGBoost实例及调参

    上一节对XGBoost算法的原理和过程进行了描述,XGBoost在算法优化方面主要在原损失函数中加入了正则项,同时将损失函数的二阶泰勒展开近似展开代替残差(事实上在GBDT中叶子结点的最优值求解也是使 ...