DQL是用于查询表中数据的语言。
SELECT 子句
FROM 子句
WHERE 子句JOIN...ON...子句
GROUP BY 子句
HAVING 子句
ORDER BY子句
一条DQL语句至少要包含的两个子句分别是SELECT子句和FROM子句
由SELECT和FROM构成。
SELECT子句和FROM子句
SELECT 字段1[,字段2,字段3,...]
FROM 表1[,表2,表3...]
SELECT子句中可以使用*表达查询所有的字段
实际开发中不推荐使用,因为查询低效*
例
查询teacher表中的所有数据
SELECT * FROM teacher
上述SQL执行时,数据库会先解析"*",这个操作会导致数据库先查看内部数据字典了解表的字段后
才能查看表中数据。由于查询是非常频繁的操作,因此每次查看数据字段无疑是浪费性能且消耗时间的操作!
全字段查询时应当在SELECT子句中将所有字段全部列出来(后期java程序执行时)。
如果是手动临时查询,可以使用*。查看每个老师的名字,职称,工资,性别
SELECT name,title,salary,gender
FROM teacher
在DQL中用于筛选查询的记录。最终数据库仅将满足WHERE子句条件的记录体现在结果集中。
例
查看职称为"一级讲师"的老师名字和工资?
1:查询的是老师信息,能确定FROM子句中的表名为teacher
2:查看的是老师的名字和工资,能确定SELECT子句中的字段name和salary
3:由于仅查看"一级讲师",能确定WHERE子句过滤条件为title='一级讲师'
SELECT name,salary,title
FROM teacher
WHERE title='一级讲师'
查看除’刘苍松’老师以外的其他老师的名字,工资和年龄?
SELECT name,salary,age
FROM teacher
WHERE name<>'刘苍松'
查看所有职位是’大队长’的同学的名字年龄和性别
SELECT name,age,gender
FROM student
WHERE job='大队长'
查看年龄在30(含)岁以上的老师都有谁?查看老师的名字,年龄,性别,工资
SELECT name,age,gender,salary
FROM teacher
WHERE age>=30
例
查看7岁的大队长都是谁?列出:名字,年龄,性别,职位
SELECT name,age,gender,job
FROM student
WHERE job='大队长' AND age=7
查看班级编号小于6的所有中队长的名字,年龄,性别,职位和所在班级编号
SELECT name,age,gender,job,class_id
FROM student
WHERE class_id<6 AND job='中队长'
查看所有一级讲师和三级讲师的名字,职称,工资?
SELECT name,title,salary
FROM teacher
WHERE title='一级讲师' OR title='三级讲师'
查看所有大队长,中队长和小队长的名字,年龄,性别
SELECT name,age,gender
FROM student
WHERE job='大队长' OR job='中队长' OR job='小队长'
查看班级编号在6(含)以下的所有大队长和中队长的名字,年龄,职位,班级编号
AND的优先级是高于OR的
可以使用()提高优先级
SELECT name,age,job,class_id
FROM student
WHERE class_id<=6 AND job='大队长' OR job='中队长'
上述SQL的条件应当读作:查看班级编号6以下的大队长和所有班级编号的中队长SELECT name,age,job,class_id
FROM student
WHERE class_id<=6 AND (job='大队长' OR job='中队长')
提高OR的优先级满足查询要求
例
查看所有的大队长,中队长,小队长的名字,年龄,性别
SELECT name,age,gender
FROM student
WHERE job='大队长' OR job='中队长' OR job='小队长'
等价于
SELECT name,age,gender
FROM student
WHERE job IN('大队长','中队长','小队长')
查看所有一级讲师,二级讲师,三级讲师的老师名字,职称和工资?
SELECT name,title,salary
FROM teacher
WHERE title IN ('一级讲师','二级讲师','三级讲师')
SELECT name,title,salaryFROM teacherWHERE title NOT IN('一级讲师','二级讲师')
查看不是中队长和大队长以及小队长的其他学生的名字,年龄,职位
SELECT name,age,job
FROM student
WHERE job NOT IN('大队长','中队长','小队长')
查看工资在2000-5000之间的老师的名字,工资,职称?
SELECT name,salary,title
FROM teacher
WHERE salary>=2000 AND salary<=5000
等价于
SELECT name,salary,title
FROM teacher
WHERE salary BETWEEN 2000 AND 5000下限 上限
查看年龄在7-10岁之间的学生的名字,年龄,性别
SELECT name,age,gender
FROM student
WHERE age BETWEEN 7 AND 10
查看年龄在20-35岁之间的男老师的名字,职称,年龄
SELECT name,title,age
FROM teacher
WHERE age BETWEEN 20 AND 35
AND gender='男'
查看3-5楼的班级名称都是什么?
SELECT name
FROM class
WHERE floor BETWEEN 3 AND 5
语法
SELECT DISTINCT 字段1[,字段2,...]
FROM 表名
...
例
查看老师的职称都有哪些?
SELECT title
FROM teacher
上述SQL语句的查询结果集是展现每个老师的职称,与查询需求不匹配SELECT DISTINCT title
FROM teacher
将查询结果集中重复的title去除后得到正确效果
查看学生的职位都有哪些?
SELECT DISTINCT job
FROM student
查看各年龄的职位都有哪些?
SELECT DISTINCT age,job
FROM student
练习:
1.查看负责课程编号(subject_id)为1的男老师都有谁?SELECT name,salary,titleFROM teacherWHERE subject_id=1 AND gender='男'2.查看工资高于5000的女老师都有谁?SELECT name,salary,titleFROM teacherWHERE salary>5000 AND gender='女'3.查看工资高于5000的男老师或所有女老师的工资?SELECT name,salary,genderFROM teacherWHERE salary>5000 AND gender='男' OR gender='女'4.查看所有9岁学生的学习委员和语文课代表都是谁?SELECT name,job,ageFROM studentWHERE age=9 AND (job ='学习委员' OR job='语文课代表')5.查看工资在6000到10000之间的老师以及具体工资?SELECT name,salary,titleFROM teacherWHERE salary BETWEEN 6000 AND 100006.查看工资在4000到8000以外的老师及具体工资?SELECT name,salary,titleFROM teacherWHERE salary NOT BETWEEN 4000 AND 80007.查看老师负责的课程编号都有什么?SELECT DISTINCT subject_idFROM teacher8.查看所有女老师的职称都是什么?SELECT DISTINCT titleFROM teacherWHERE gender='女'9.查看7-10岁的男同学的职位都有哪些?SELECT DISTINCT jobFROM studentWHERE age BETWEEN 7 AND 10AND gender='男'10.查看一级讲师和二级讲师的奖金(comm)是多少?SELECT name,commFROM teacherWHERE title IN ('一级讲师','二级讲师')11.查看除老板和总监的其他老师的工资和奖金是多少?SELECT name,title,salary,commFROM teacherWHERE title NOT IN('老板','总监')12.查看'3年级2班'和'5年级3班'在那层楼?SELECT name,floorFROM classWHERE name IN('3年级2班','5年级3班')
LIKE中有两个通配符:
组合示意:
%X%:字符串中含有X。
X%:字符串是以X字符开始的。
%X:字符串是以X字符结尾的。
__X:三个字符,且最后一个字符是X的。
%X_:倒数第二个字符是X的。
例
查看名字中含有’苍’的老师?
SELECT name,title,salary
FROM teacher
WHERE name LIKE '%苍%'
查看姓’张’的学生都有谁?
SELECT name,job,gender,age
FROM student
WHERE name LIKE '张%'
查看名字是以’晶’结尾的老师都有谁?
SELECT name,title,salary
FROM teacher
WHERE name LIKE '%晶'
查看三个字名字且最后一个字是’平’的学生都有谁?
SELECT name,job,gender,age
FROM student
WHERE name LIKE '__平'
查看三个字名字中第二个字符是’平’的学生都有谁?
SELECT name,job,gender,age
FROM student
WHERE name LIKE '__平'
查看职位是’什么课什么表’的学生都有谁?
SELECT name,job,gender,age
FROM student
WHERE job LIKE '%课%表'
查看所有2班都在哪层?
SELECT name,floor
FROM class
WHERE name LIKE '%2班'
练习
1.查询名字姓"李"的学生姓名SELECT name,ageFROM studentWHERE name LIKE '李%'2.查询名字中包含"江"的学生姓名SELECT name,ageFROM studentWHERE name LIKE '%江%'3.查询名字以"郭"结尾的学生姓名SELECT name,ageFROM studentWHERE name LIKE '%郭'4.查询9-12岁里是"课代表"的学生信息SELECT name,age,jobFROM studentWHERE age BETWEEN 9 AND 12AND job LIKE '%课代表'5.查询名字第二个字是"苗"的学生信息SELECT name,ageFROM studentWHERE name LIKE '_苗%'6.查询姓"邱"的课代表都是谁?SELECT name,jobFROM studentWHERE name LIKE '邱%'AND job LIKE '%课代表'
例:
查看没有奖金的老师都有谁?(奖金字段值为null的记录)
SELECT name,salary,comm
FROM teacher
WHERE comm=NULL
上述SQL是查询不到任何记录的,因为comm的值不能用=来判断NULL。SELECT name,salary,comm
FROM teacher
WHERE comm IS NULL
查看有奖金的老师都有谁?
SELECT name,salary,comm
FROM teacher
WHERE comm IS NOT NULL
ORDER BY子句用于指定查询的结果集按照指定的字段进行排序
例:
查看老师工资的排名情况
SELECT name,salary,title
FROM teacher
ORDER BY salary DESC
查看老师的奖金情况,按照从少到多排序。
SELECT name,comm
FROM teacher
ORDER BY comm
查看学生的生日从远到近。
日期字段排序是,越早的日期越小,越晚的日期越大。
SELECT name,birth
FROM student
ORDER BY birth
查看7-10岁学生名字,年龄,生日。查看时按照年龄从小到大。
SELECT name,age,birth
FROM student
ORDER BY age,birth DESC
查看老师的奖金和工资,按照奖金的升序,工资的降序
SELECT name,comm,salary
FROM teacher
ORDER BY comm,salary DESC;
当一条DQL语句可以查询出很多行记录时,为了减少资源开销,以及网络间的传送速度,我们通常都会使用分页查询来分批,分段的将DQL查询的结果集获取到。
分页是方言,标准SQL92标准中没有对分页的语法定义。
在MYSQL中分页使用LIMIT实现。在ORACLE中使用ROWNUM实现
在ORDER BY子句中使用LIMIT N,M
ORDER BY 字段
LIMIT N,M
N表示跳过结果集的记录数
M表示从跳过N条记录后开始连续显示M条记录
分页上两个条件:1:页数 2:每页显示的条数
N的公式:(页数-1)*每页显示的条数
M:每页显示的条数
例如:一页显示15条,显示第3页?
LIMIT (3-1)*15,15
例:
查看老师工资排名的前5名是谁?
SELECT name,salary
FROM teacher
ORDER BY salary DESC
LIMIT 0,5
按照老师奖金的降序排序后,每页显示3条,显示第5页
- N的公式:(页数-1)*每页显示的条数
- M:每页显示的条数
SELECT name,comm
FROM teacher
ORDER BY comm DESC
LIMIT 12,3
在SELECT子句中使用函数或表达式
例:
查看每个老师的年薪是多少?
SELECT name,salary,salary*12
FROM teacher
在计算表达式中,任何数字与NULL运算结果都是NULL
IFNULL(arg1,arg2)函数
当arg1不为NULL时,函数返回arg1的值
当arg1为NULL时,函数返回arg2的值
IFNULL作用时将一个NULL值换成一个非NULL值
内部逻辑
IFNULL(arg1,arg2){if(arg1!=null){return arg1;}else{return arg2}
}
例:
查看每个老师的工资+奖金是多少?
SELECT name,salary,comm,salary+comm
FROM teacher
上述SQL对于salary+comm而言,若comm字段为NULL时计算结果也为NULLSELECT name,salary,comm,IFNULL(comm,0)
FROM teacher
上述SQL会将comm字段为null的记录将该字段改为0查看老师工资+奖金的实际写法:
SELECT name,salary,comm,salary+IFNULL(comm,0)
FROM teacher
例
查看年薪小于6万的老师都有谁?
SELECT name,salary,salary*12
FROM teacher
WHERE salary*12<60000 查询时只有该条记录salary字段值*12小于60000的会被查出
例:
查看奖金小于3000的老师都有谁?
比较运算时也会忽略NULL值的
SELECT name,comm
FROM teacher
WHERE comm<3000
上述查不出奖金字段为NULL的记录。SELECT name,comm
FROM teacher
WHERE IFNULL(comm,0)<3000
别名可以在SELECT子句中为函数,表达式取别名,是的结果集中该字段可读性更强。
别名也可被用在其他子句上,比如在FROM子句中为表取别名,便于关联查询。
当SELECT子句中含有函数或表达式时,通常都会指定别名
字段名 别名
SELECT salary*12 salary
字段名 AS 别名
SELECT salary*12 AS salary
字段名 [AS] ‘字段名’
SELECT salary*12 AS 'salary'
或
SELECT salary*12 'salary'
字段名 [AS] “字段名”
SELECT salary*12 AS "salary"
或
SELECT salary*12 "salary"
当别名中含有SQL关键字或空格时要加引号
SELECT name,salary*12 from 由于from是关键字,SQL语句语法错误(两次FROM)
FROM teacher
正确写法
SELECT name,salary*12 'from'
FROM teacher下述SQL本意为salary*12取别名"annu sal"
SELECT name,salary*12 annu sal 数据库理解annu为别名,再空格sal认为语法错误
FROM teacher
正确写法
SELECT name,salary*12 'annu sal'
FROM teacher
例:
查看每个老师的年薪是多少?
SELECT name,salary*12 salary
FROM teacher
练习
1.查询所有10岁学生的生日,按生日对应的年纪从大到小.SELECT name,age,birthFROM studentWHERE age=10ORDER BY birth2.查询8岁同学中名字含有"苗"的学生信息SELECT name,ageFROM studentWHERE age=8AND name LIKE '%苗%'3.查询负责课程编号1和2号且工资高于6000的老师信息SELECT name,salary,subject_idFROM teacherWHERE salary>6000AND subject_id IN (1,2)4.查询10岁以上的语文课代表和数学课代表SELECT name,age,jobFROM studentWHERE age>10AND job IN ('语文课代表','数学课代表')5.查询不教课程编号1的老师信息,按照工资降序排序SELECT name,salary,subject_idFROM teacherWHERE subject_id<>1ORDER BY salary DESC6.查询没有奖金的老师信息SELECT name,commFROM teacherWHERE IFNULL(comm,0)=07.查询所有老师的奖金,并按照奖金降序排序SELECT name,commFROM teacherORDER BY comm DESC8.查看工资高于8000的老师负责的课程编号都有那些?SELECT DISTINCT subject_idFROM teacherWHERE salary>80009.查看全校年龄最小学生的第6-10名SELECT name,age,birthFROM studentORDER BY birth DESCLIMIT 5,5
聚合函数(也称为多行函数,分组函数)是用来对结果集按照指定字段统计的。
聚合函数可以将多行记录中的指定字段统计出一条结果。
聚合函数:
MIN,MAX,AVG,SUM是对字段值的统计。COUNT是对记录数的统计。
使用聚合函数时,通常要先将参与统计的记录查询出来后再决定添加何种聚合函数进行统计。
例
查看所有老师的平均工资是多少?
1:准备参与统计的记录对应的SQL语句
下述SQL用来查询出所有老师的工资:
SELECT salary
FROM teacher2:为salary字段添加聚合函数,求所有记录salary的平均值
SELECT AVG(salary)
FROM teacher
查看所有老师的最高工资,最低工资,工资总和和平均工资分别是多少?
SELECT MAX(salary),MIN(salary),SUM(salary),AVG(salary)
FROM teacher
查看负责课程编号1的老师的平均工资是多少?
1:查询出负责课程编号1的老师工资分别是多少?
SELECT salary
FROM teacher
WHERE subject_id=12:在上述SQL中对salary字段添加聚合函数求平均值
SELECT AVG(salary)
FROM teacher
WHERE subject_id=1
查看共有多少位老师?
COUNT(*)作为统计被所有数据库都进行了优化,因此统计记录数时就用它
SELECT COUNT(name)
FROM teacher
上述SQL统计结果共20条。teacher表中每条记录的name都有值SELECT COUNT(comm)
FROM teacher
上述SQL统计结果共17条。原因:teacher表中有3条记录comm字段值为NULL
聚合函数是忽略NULL值的SELECT COUNT(*)
FROM teacher
查看所有老师的平均奖金
SELECT AVG(comm),SUM(comm)
FROM teacher
上述SQL是对comm字段有的所有记录取平均值将NULL值替换为非NULL值再进行统计
SELECT AVG(IFNULL(comm,0))
FROM teacher
查看负责课程编号1的老师共几人?
SELECT COUNT(*)
FROM teacher
WHERE subject_id=1
查看班级编号(class_id)为1的学生有多少人?
SELECT COUNT(*)
FROM student
WHERE class_id=1
查看全校学生生日最大的是哪天?
SELECT MIN(birth)
FROM student
查看11岁的课代表总共多少人?
SELECT COUNT(*)
FROM student
WHERE age=11
AND job LIKE '%课代表'
GROUP BY子句在DQL语句中是对查询结果集按照指定的字段值相同的记录进行分组,配合聚合函数进行组内统计。
若DQL的SELECT子句中没有聚合函数时,不会使用GROUP BY子句。
在SELECT子句中不在聚合函数中的字段都必须出现在GROUP BY子句中
例
教每门课程的老师的平均工资是多少?
SELECT AVG(salary),subject_id
FROM teacher
GROUP BY subject_idGROUP BY子句的作用是将:
SELECT salary,subject_id
FROM teacher
查询结果集按照subject_id字段值相同的记录分组,在组内统计结果。
查看每个班级各多少学生?(将student表中所有记录按照class_id字段值相同的记录分组,组内统计记录数)
SELECT COUNG(*),class_id
FROM student
GROUP BY class_id
查看学校每种职位的学生各多少人?以及最大生日和最小生日
SELECT COUNT(*) '人数',MIN(birth) '最大生日',MAX(birth) '最小生日',job
FROM student
GROUP BY job
GROUP BY子句若指定了多个字段,那么只有当这几个字段值都相同的记录才会被划分为一组。
例
查看每个班每种职位各多少人?
SELECT COUNT(*),job,class_id
FROM student
GROUP BY job,class_id
在SELECT子句中为聚合函数取别名,这样方便在ORDER BY子句中排序
例
查看每个科目老师的平均工资,并按照平均工资从少到多排序
SELECT AVG(salary),subject_id
FROM teacher
GROUP BY subject_id
ORDER BY AVG(salary)建议为聚合函数取别名,并按照该别名排序
SELECT AVG(salary) avg,subject_id
FROM teacher
GROUP BY subject_id
ORDER BY avg
例
仅查看平均工资高于6000的那些课程的老师平均工资
SELECT AVG(salary),subject_id
FROM teacher
WHERE AVG(salary)>6000
GROUP BY subject_id
执行后报错:
原因:过滤实际不同
WHERE条件实在检索表中数据时,每检索一行记录就会进行一次WHERE,来决定该条记录是否被查询出来
聚合函数想作为过滤条件(将统计结果作为过滤条件),统计的前提时要先查询出结果集,而查询结果集是WHERE的实际。因此根据统计结果再进行过滤应当已经是WHERE之后进行的了。
HAVING子句仅跟在GROUP BY之后。因此若没有GROUP BY子句就不会写HAVING子句。
HAVING子句也是用于添加过滤条件的,过滤时机:分组统计出结果后进行二次过滤的。
HAVING子句是对分组过滤的:只有满足HAVING子句条件的分组才会进行SELECT中相应的统计。
WHERE子句是对记录过滤的:只有满足WHERE子句条件的记录才会进行SELECT中相应的查询
WHERE先执行,用于确定查询出的结果集。HAVING后执行用于确定保留结果集中的那些分组
例
仅查看平均工资高于6000的那些课程的老师平均工资
子句执行顺序
SELECT AVG(salary),subject_id 4:最后查询对应的内容(仅查询满足HAVING要求的组)
FROM teacher 1:确定数据来自哪里
GROUP BY subject_id 2:确定数据按照哪个字段分组(按照subject_id分6组)
HAVING AVG(salary)>6000 3:确定仅保留哪些分组(仅有3组符合AVG要求)
查看每个科目老师的平均工资,前提是该科老师最高工资高于9000.
SELECT AVG(salary),subject_id 4:最后将过滤出的2组进行统计结果
FROM teacher 1:确定数据来自teacher表
GROUP BY subject_id 2:按照subject_id字段值相同的可被分出6组
HAVING MAX(salary)>9000 3:分出的6组都要看最高工资是否>9000,最终过滤出2组。
查看科目老师的工资总和是多少?前提是该科老师的平均奖金要高于4000.
SELECT SUM(salary),subject_id
FROM teacher
GROUP BY subject_id
HAVING AVG(IFNULL(comm,0))>4000
嵌套在其他SQL语句中的一条DQL语句就被称为子查询。
在DQL中子查询部分要被"()"括起来使用
例:
查看哪个老师的工资高于王克晶的工资?
查询王克晶的工资是多少?
SELECT salary
FROM teacher
WHERE name='王克晶'
通过上述SQL我们可以得到一个单行单列的查询结果集:salary===>8000
查看谁的工资高于8000(王克晶的工资)?
SELECT name,salary
FROM teacher
WHERE salary>8000
将步骤1的SQL替换为步骤2的8000
示意:
int money = SELECT salary FROM teacher WHERE name='王克晶' 不是真实语法!!!
查询示意:
SELECT name,salary
FROM teacher
WHERE salary>money真实写法:
SELECT name,salary
FROM teacher
WHERE salary>(SELECT salary FROM teacher WHERE name='王克晶')
查看那些高于老师平均工资的老师工资都是多少?
1:查看老师的平均工资是多少?
SELECT AVG(salary)
FROM teacher2:谁的工资高于平均工资?
SELECT name,salary
FROM teacher
WHERE salary>(SELECT AVG(salary)FROM teacher)
查看和’李费水’在同一个班的学生都有谁?
1:查看‘李费水’所在班级的班级号
SELECT class_id
FROM student
WHERE name='李费水'2:查看和'李费水'在同一个班的学生都有谁?
SELECT name,class_id
FROM student
WHERE class_id=(SELECT class_idFROM studentWHERE name='李费水')
查看工资最高的老师的工资和奖金是多少?
1:最高工资是多少?
SELECT MAX(salary) FROM teacher2:查看工资最高的老师的工资和奖金是多少?
SELECT name,salary,comm
FROM teacher
WHERE salary=(SELECT MAX(salary) FROM teacher)
** 在单行单列子查询中,若我们使用其作为过滤条件使用时,可以搭配:=, >, >=, <, <=, <>使用**
** 在多行单列子查询中(查询结果集有多个值),在过滤条件中要搭配:IN,ANY,ALL**
ANY与ALL是与:>, >=, <, <=联合使用的
IN(列表)或NOT IN(列表):在列表中或不在列表中
上述所说的列表指的是一个多行单列子查询的结果集
例
查看与"祝雷"和"李费水"在同一个班的学生都有谁?
1:查看祝雷和李费水的班级号?
SELECT class_id
FROM student
WHERE name IN('祝雷','李费水')2:查看与"祝雷"和"李费水"在同一个班的学生都有谁?
SELECT name,class_id
FROM student
WHERE class_id=(SELECT class_idFROM studentWHERE name IN('祝雷','李费水'))
上述SQL执行后会报错,因为子查询返回了多个值,"="不能同时等于多个值
正确写法:
SELECT name,class_id
FROM student
WHERE class_id IN(SELECT class_idFROM studentWHERE name IN('祝雷','李费水'))
查看比教科目2和科目4老师工资都高的老师都有谁?
1:查看科目2和科目4老师的工资都是多少?
SELECT salary FROM teacher WHERE subject_id IN(2,4)2:查看比教科目2和科目4老师工资都高的老师都有谁?
SELECT name,salary,subject_id
FROM teacher
WHERE salary>ALL(SELECT salary FROM teacher WHERE subject_id IN(2,4))
例:
将负责与"范传奇"教同一科目的所有老师工资涨500
1:查看范传奇负责的科目号?
SELECT subject_id
FROM teacher
WHERE name='范传奇'2:更新数据
UPDATE teacher
SET salary=salary+500
WHERE subject_id=(SELECT subject_idFROM teacherWHERE name='范传奇')
** 在创建表时,可以将一个子查询的结果集当作表创建出来。后期使用的视图也是如此。**
例:
创建一张表用于记录老师工资的统计情况(按照科目)。要记录每门课老师的最高工资,最低工资,平均工资和工资总和以及科目编号。表名:teacher_salary_info
1:创建表
CREATE TABLE teacher_salary_info(max_salary INT,min_salary INT,avg_salary INT,sum_salary INT,subject_id INT
)
2:先执行DQL查询对应结果,在使用DML中的INSERT语句逐行插入。若数据太多,工作量太大且笨重。
SELECT MAX(salary),MIN(salary),AVG(salary),SUM(salary),subject_id
FROM teacher
GROUP BY subject_id实际写法:
注意:如果子查询的SELECT子句中的字段是函数或表达式则必须要指定别名(会作为新创建的表的字段名)
CREATE TABLE teacher_salary_info
AS
SELECT MAX(salary) max_sal,MIN(salary) min_sal,AVG(salary) avg_sal,SUM(salary) sum_sal,subject_id
FROM teacher
GROUP BY subject_id
结果集中的字段来自于多张表。联合多张表进行查询。
表与表之间的数据存在着一种对应关系,这种对应关系被称为表与表之间的关联关系。
表之间的关联关系分为三种:
一对一:A表的一条记录仅对应B表的一条记录。反之亦然。
一对多:A表的一条记录对应B表的多条记录,反之B表的一条记录仅对应A表的一条记录。A与B是一对多的。
多对多:当两张表双向都是一对多时就是多对多关系。
在关联查询中必须要指定连接条件,连接条件作用是让数据库直到A表的记录与B表的哪些记录对应
关联查询中不指定连接条件会产生笛卡尔积,笛卡尔积通常是一个无意义的结果集(少数特殊业务除外)
多张表进行关联查询时,要满足当N张表联合查询时要指定最少N-1个连接条件。
缺少连接条件产生笛卡尔积
特点:
以两张表A和B关联查询,结果集中包含的数据A表每条记录与B表每条记录产生的记录数。记录总数应当时A表记录数*B表记录数。
SELECT 字段...
FROM 表A,表B,...
WHERE 连接条件
AND 过滤条件
注意:如果在关联查询中含有过滤条件时必须与连接条件同时满足,否则会产生笛卡尔积
例
查看类名老师的名字和其任课的科目名称?
SELECT t.name,s.name
FROM teacher t,subject s
WHERE t.subject_id=s.id实际查询时,数据库会从teacher表中将其中一条记录与subject表中的每条记录都关联一次,但是仅将符合连接条件的记录分别取出查询的字段构成结果集中的一条记录。
查看班级的名称和对应的班主任(老师)是谁?
1:数据需要来自哪些表?
班级名称来自class表。老师名字来自teacher表。
明确FROM子句内容:FROM class c,teacher t2:明确class表与teacher表记录之间的对应关系(关联关系)
class表记录中teacher_id字段的值与teacher表记录中id字段的值相同的记录产生对应关系。
明确WHERE子句连接条件:WHERE c.teacher_id=t.idSELECT c.name,t.name
FROM class c,teacher t
WHERE c.teacher_id=t.id
查看每个学生的名字,年龄,以及其所在的班级名称和所在楼层
1:确定数据来自哪些表?
学生信息来自student表。班级信息来自class表
明确FROM子句:FROM student s,class c2:student表与class表记录的对应关系?
学生表某条记录的class_id值与class表某记录的id值相同的产生对应关系
明确WHERE子句连接条件:s.class_id=c.idSELECT s.name,s.age,c.name,c.floor
FROM student s,class c
WHERE s.class_id=c.id
过滤条件要与连接条件同时满足
例
"王克晶"是哪个班的班主任?查看班级名称,所在楼层和班主任名字以及工资
SELECT c.name,c.floor,t.name,t.salary
FROM class c,teacher t
WHERE c.teacher_id=t.id
AND t.name='王克晶'
查看三年级的班级班主任都是谁?要列出班级名称,所在楼层,班主任名字和工资
SELECT c.name,c.floor,t.name,t.salary
FROM class c,teacher t
WHERE c.teacher_id=t.id
AND c.name LIKE '3年级%'
查看5年级的中队长都有谁?要列出学生名字,年龄,性别,职位和所在班级的名字以及楼层
SELECT s.name,s.age,s.gender,s.job,c.name,c.floor
FROM student s,class c
WHERE s.class_id=c.id 连接条件
AND c.name LIKE '5年级%' 过滤条件
AND s.job='中队长' 过滤条件
例
查看"范传奇"所带班级的学生都有谁?要列出:学生名字,年龄,班级名称,老师名字
1:查询的数据来自哪些表
学生信息来自student表。班级信息来自class表。老师信息来自teacher表
明确FROM子句:FROM student s,class c,teacher t2:明确连接条件3张表关联至少要有2个连接条件2.1:学生表与班级表中的记录对应关系s.class_id=c.id2.2:班级表与老师表中的记录对应关系c.teacher_id=t.id3:过滤条件来自哪张表?老师名字叫"范传奇",来自teacher表SELECT s.name,s.age,c.name,t.name
FROM student s,class c,teacher t
WHERE s.class_id=c.id 连接条件
AND c.teacher_id=t.id 连接条件 注:所有的连接条件要同时满足
AND t.name='范传奇' 过滤条件
查看1年级1班的同学的名字和来自的城市
1:数据来自那些表
城市信息来自location表。学生信息来自student表2:过滤条件来自哪些表?
查看1年级1班的。条件来自class表。
确定WHERE子句的过滤条件:c.name='1年级1班'上述两条联合确定
FROM子句:FROM location l,student s,class c3:连接条件3.1:班级与学生的连接条件:c.id=s.class_id3.2:学生与城市的连接条件:s.location_id=l.id
WHERE子句连接条件:WHERE c.id=s.class_id AND s.location_id=l.id SELECT s.name,l.name
FROM location l,student s,class c
WHERE c.id=s.class_id AND s.location_id=l.id 连接条件
AND c.name='1年级1班' 过滤条件
练习:
1.查看来自北京的学生都是谁?
2.教"英语"的老师都是谁?
3.刘苍松所带班级的学生都有谁?
4.教语文的老师所带的班级有哪些?
5.王克晶所带的班级学生都来自哪些城市(去重)?
6.3年级的几个班主任都教哪些课程?
7.工资高于10000的老师所带班里的大队长都是谁?
8."李费水"的班主任教哪门课?
9.所在4楼的班里的大队长和中队长以及班主任都是谁?
10.全校最小的同学的班主任是谁?
HAVEING : 后执行,过滤分组,仅在GROUP BY后
WHERE : 先执行, 过滤记录