前言

现在大多数开发工作中,已经可以使用一些组件或框架提供的强大的条件构造器来完成查询数据了,虽然强大而且方便,但也还是存在很多业务场景需要实打实的编写传统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. adb - Performing Push Install adb: error: failed to get feature set: more than one 解决方案

    问题背景 直接 adb install 包名  无法安装成功 解决方案 安装 adb -s 10.200.241.215:5555 install test.apk 删除 adb -s 10.200. ...

  2. Git 系列教程(11)- 分支简介

    前言 很多版本控制系统都有分支这个概念 使用分支意味着可以将日常工作从主线上脱离,从而避免影响主线 Git 鼓励在工作流程中频繁使用分支和合并 Git 是如何保存数据的 Git 保存的不是文件的变化或 ...

  3. BFD协议简介

    1. 背景 双向转发检测BFD(Bidirectional Forwarding Detection)是一种全网统一的检测机制,用于快速检测.监控网络中链路或者IP路由的转发连通状况. 为了保护关键应 ...

  4. Java关键字-static汇总

    1.静态变量(被static修饰的成员变量) 1-静态变量 运行时,Java虚拟机只为静态变量分配一次内存(加载类的过程中完成静态变量的内存分配) 类的内部可以在任何方法内直接访问静态变量 其他类中可 ...

  5. 小白也能看懂的dubbo3应用级服务发现详解

    搜索关注微信公众号"捉虫大师",后端技术分享,架构设计.性能优化.源码阅读.问题排查.踩坑实践. 本文已收录 https://github.com/lkxiaolou/lkxiao ...

  6. 开源自己编写的半人工标注平台PaddleOCRLabel(.NET Winform版本)

    大家好, 我是博客园的老用户了,许久不做.NET技术了,从2013年起,开始从事App技术,写过书,在Linux上搭建区块链,用GO写智能合约,使用nodejs搭建过微服务,用python写过爬虫,写 ...

  7. 【第六篇】- Maven 仓库之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 仓库 在 Maven 的术语中,仓库是一个位置(place). Maven 仓库是项目中依赖的第三方库,这个库所在的位置叫做仓库. 在 Maven 中,任何一个依赖.插件或者项目构建的输出 ...

  8. windows 中cmd一些特殊命令

    chcp 65001  就是换成UTF-8代码页 chcp 936 可以换回默认的GBK chcp 437 是美国英语 shutdown -s -t 60   60秒后关机 shutdown /a  ...

  9. dede5.7 给栏目添加上缩略图

    如我们一个栏目列表都用缩略图来表示,而不仅仅只是文字,如果没有这项功能会非常麻烦,网上有很多这方面的资料,但是都试过了有很多问题,自己研究一下,测试基本通过.新加字段 typeimg后台执行SQL: ...

  10. 最新seo优化技巧

    国内的SEO也发展不少年份了.我是最早开始从事SEO的那一班人.看着这个行业从零开始发展,长大.成熟还谈不上.可以这样说吧,国内做这个行业的,高手并不多.实战的高手更是寥寥无几.当然这个是我个人的推断 ...