美文网首页软件测试
mysql数据库小知识----查询语言DQL

mysql数据库小知识----查询语言DQL

作者: 小高有点 | 来源:发表于2020-05-29 15:10 被阅读0次

    第一章 SQL的基本语法规范

    1.sql不区分大小写,但是习惯上关键字、系统保留字、函数名称大写,表名和列名小写

    2.sql使用空格或者回车来分隔每个单词都一样,习惯上每个子句换行
    WHERE子句中的每个条件占一行,子查询单独占一行

    3.复杂的语句最好加上注释进行说明

    -- 单行注释(空格必须有)
    /*
    多行注释
    */
    

    4.sql语句中使用分号作为分隔符,系统读取到分号才会执行语句

    /*
    select 列名1,列名2,……列名n定义查询数据所在的列
    
    from 表名1,表名2,……表名n  定义查询数据所在的表
    
    where 限定条件1 and/or 限定条件2 ......  定义查询数据的限定条件(行)
    
    group by 列名1,列名2,……列名n定义分组函数的分组方式
    
    having 分组条件1 and/or 分组条件2……  定义分组函数结果的限定条件
    
    order by 列名1 asc/desc,列名2 asc/desc ......  定义查询结果的排序方式
    
    */
    

    第二章 SELECT基础

    1.*代表所有列

    SELECT * FROM emp;
    
    SELECT * FROM dept;
    
    SELECT * FROM salgrade;
    
    SELECT * FROM bonus;
    

    2.查询指定的列

    SELECT ename,job,sal,deptno FROM emp;
    

    3.对查询结果进行运算
    # + - * /

    查询每个员工的年薪
    SELECT ename,12*sal FROM emp;
    #员工的年终奖定为年薪的10%再加上500
    SELECT ename,(12*sal)*0.1+500 FROM emp;
    

    4.空值参与运算得到结果也是空值

    #计算员工的年收入
    SELECT ename,sal,comm,12*(sal+comm) FROM emp;
    

    5.别名

    #查询结果中可以给列起别名加以说明
    /*
    列名 别名
    列名 AS 别名
    别名中如果包含特殊字符(空格),需要加双引号
    双引号只会在起别名的时候出现,其他的所有地方都只能用单引号而不能用双引号
    */
    SELECT ename xingming,job zhiwei FROM emp;
    SELECT ename AS xingming,job AS zhiwei FROM emp;
    SELECT ename 姓名,job 职位 FROM emp;
    
    SELECT ename "xing ming",job "zhi wei" FROM emp;
    
    #别名主要用来标识运算结果
    SELECT ename,(12*sal)*0.1+500 AS nianzhongjiang FROM emp;
    

    6.表达式

    #表达式根据数据类型的不同分为数字表达式、字符表达式和日期表达式
    #手动输入的表达式可以写在select后面,表中有多少行,表达式就显示多少次
    #手动输入数字表达式可以直接写,日期和字符表达式必须加上单引号
    SELECT 123.456,12*60*48,'I am the king' FROM emp;
    
    #mysql允许只写select,不写from;oracle必须要写select和from,不能缺少
    #如果要查询的数据都是手动输入,与表中数据无关,可以不写from
    
    SELECT 123.456,12*60*48,'I am the king';
    SELECT 'who are you',ename FROM emp;
    SELECT job,'JOB' FROM emp;
    #手动字符串必须加单引号,mysql在windows平台字符串不区分大小写,但是在linux区分大小写
    #其他的数据库包括编程语言,字符串都要区分大小写
    

    7.distinct去重

    SELECT job FROM emp;
    SELECT DISTINCT job FROM emp;
    SELECT DISTINCT deptno FROM emp; 
    #多列去重
    SELECT DISTINCT job,deptno FROM emp;
    #普通列不能和去重的列同时查询,因为行数不匹配,不能组成一张表
    #select ename,distinct job from emp;
    

    8.limit分页查询

    SELECT * FROM emp;
    #如果在查询结果中,想要得到固定某几行的结果,使用limit
    #limit 写在查询语句最后
    #limit m,n 表示从第m行开始显示n行数据,第一行的行号是0
    SELECT * FROM emp
    LIMIT 2,5;
    
    #limit n  表示显示前n行数据
    SELECT * FROM emp
    LIMIT 3;
    

    第三章 限定和排序

    1.where子句限定范围

    #where子句后面必须是一个完整的逻辑表达式,结果只有两种true或者false
    #在where子句中,逻辑表达式通常是比较运算,比较条件是否满足
    # =  >  <  >=  <=  !=(<>)
    #where子句限定条件通常是用表中的某一列数据作为条件,返回满足条件的数据
    
    #查询20号部门的员工信息
    SELECT * FROM emp
    WHERE deptno = 20;
    
    #查询工资高于2000的员工信息
    SELECT * FROM emp
    WHERE sal > 2000;
    
    #查询职位不是manager的员工信息
    SELECT * FROM emp
    WHERE job != 'MANAGER';
    #手动输入字符串要加单引号,最好在匹配的时候大小写一致
    
    #查询年薪小于20000的员工信息
    #列的别名不能出现在where子句中
    SELECT ename,job,sal,12*sal nianxin,deptno FROM emp
    WHERE 12*sal < 20000;
    
    #其他的数据库不支持*加上其他列一起查询,mysql允许
    SELECT *,12*sal nianxin FROM emp;
    
    #where子句中的条件也可以是两列数据相互比较
    SELECT * FROM emp
    WHERE sal < comm;
    
    #where子句中作为条件的列可以不出现在select后面,但是这样的语句结果不够直观
    SELECT ename,job,deptno FROM emp
    WHERE sal <= 1500;
    
    #where子句中比较运算符的两端数据类型必须一致
    #如果是其他数据库,数据类型不一致时会直接报错
    #mysql由于是弱数据类型的语言,所以不会报错,只是这样的语句没有意义
    SELECT * FROM emp
    WHERE ename > 2;
    
    #如果没有数据满足条件,则一行数据都没有
    SELECT * FROM emp
    WHERE deptno > 200;
    
    #如果有满足条件的数据,至少会返回一行,只是可能数据的值是空值
    SELECT comm FROM emp
    WHERE ename = 'SMITH';
    

    2.常用的特殊比较运算

    #in(value1,value,2...valueN), 列表匹配
    SELECT * FROM emp
    WHERE job IN ('MANAGER','CLERK','PRESIDENT');
    
    #between 最小值 and 最大值,范围匹配,最大值和最小值的位置不能变
    SELECT * FROM emp
    WHERE sal BETWEEN 1500 AND 3000;
    
    #like, 模糊匹配(对字符)
    #通配符,可以匹配或者代表其他字符的特殊符号
    # _ 表示1个任意字符
    # % 表示任意个任意字符,包括0个1个和多个
    SELECT * FROM emp
    WHERE ename LIKE 'S%';
    
    SELECT * FROM emp
    WHERE ename LIKE '%S';
    
    SELECT * FROM emp
    WHERE ename LIKE '%A%';
    
    SELECT * FROM emp
    WHERE ename LIKE '_A%';
    
    SELECT * FROM emp
    WHERE ename LIKE '_____';
    
    #is null, 匹配空值(不能写成 =null)
    SELECT * FROM emp
    WHERE comm IS NULL;
    

    3.逻辑运算

    #and 与运算,所有的条件都要满足才能返回结果
    SELECT * FROM emp
    WHERE deptno = 20
    AND sal > 2000;
    
    #or 或运算,多个条件满足任意一个就能返回结果
    SELECT * FROM emp
    WHERE deptno = 20
    OR sal > 2000;
    
    #not 非运算,返回不满足条件的结果
    SELECT * FROM emp
    WHERE NOT sal > 2000;
    #如果是数学符号的比较运算,not必须写在最前面
    #如果是英文的比较运算,not可以写在最前也可以写在运算符中间
    SELECT * FROM emp
    WHERE deptno NOT IN (10,20);
    

    4.运算优先级:数学运算>比较运算>NOT>AND>OR

    #可以使用括号改变运算优先级
    
    SELECT * FROM emp
    WHERE deptno = 20
    OR sal > 2000
    AND job IN ('MANAGER','CLERK');
    
    SELECT * FROM emp
    WHERE (deptno = 20
    OR sal > 2000)
    AND job IN ('MANAGER','CLERK');
    

    5.排序ORDER BY子句

    #order by也在查询语句的后面,但是在limit之前
    #asc 表示升序排列,默认可以不写
    #desc 表示降序排列
    SELECT * FROM emp
    ORDER BY sal ASC;
    
    #所有的数据类型都可以排序
    SELECT * FROM emp
    WHERE deptno = 20
    ORDER BY hiredate DESC;
    
    SELECT * FROM emp
    ORDER BY ename;
    
    #可以使用别名排序
    SELECT *,12*sal nianxin FROM emp
    ORDER BY nianxin DESC;
    
    #多列排序
    SELECT * FROM emp
    ORDER BY deptno,sal DESC;
    #多列排序时,有重复数据的列写在前面
    
    #查询工资排名前三的员工信息
    SELECT * FROM emp
    ORDER BY sal DESC
    LIMIT 3;
    

    【练习】

    1.查询薪水大于等于1500,且工作类别是SALESMAN的雇员信息
    SELECT * FROM emp
    WHERE sal >= 1500
    AND job = 'SALESMAN';
    
    2.查询年薪大于30000,工作类别不是MANAGER的雇员信息
    SELECT *,12*sal nianxin FROM emp
    WHERE 12*sal > 30000
    AND job != 'MANAGER';
    
    3.查询薪水在1500到3000之间,工作类别以“M”开头的雇员信息
    SELECT * FROM emp
    WHERE sal BETWEEN 1500 AND 3000
    AND job LIKE 'M%';
    
    4.查询佣金为空并且部门号为20或30的雇员信息(佣金=薪水SAL+津贴COMM) 
    SELECT *,sal+comm yongjin FROM emp
    WHERE sal+comm IS NULL
    AND deptno IN (20,30);
    
    5.查询佣金不为空或者部门号为20的雇员信息,要求按照薪水降序排列 (佣金=薪水+津贴)
    SELECT *,sal+comm yongjin FROM emp
    WHERE sal+comm IS NOT NULL
    OR deptno = 20
    ORDER BY sal DESC;
    
    6.查询年薪大于30000工作类别不是MANAGER,
    且部门号不是10或40的雇员信息,要求按照雇员姓名进行排列
    SELECT *,12*sal nianxin FROM emp
    WHERE 12*sal > 30000
    AND job != 'MANAGER'
    AND deptno NOT IN (10,40)
    ORDER BY ename;
    
    7.查询30号部门工资排名前三的员工
    SELECT * FROM emp
    WHERE deptno = 30
    ORDER BY sal DESC
    LIMIT 3;
    

    第四章 单行函数

    #函数可以实现特定的功能或者运算,给函数输入数据,函数经过处理,得到相应的结果
    f1(X)=3x+2
    f1(4)=14
    f2(X,Y)=5x+4y
    f2(3,2)=23
    
    #mysql中系统自带的单行函数,提供了数据特殊处理的方式
    #可以协助我们快速对特定数据进行处理
    #系统中的函数数量非常多,这里介绍一些常用函数
    
    #单行数据针对表中的每一行数据分别进行处理或运算,得到相应的结果
    #单行函数按照处理的数据类型分为:数值函数,字符函数,日期函数,逻辑函数
    

    1.数值函数

    #round(m,n) 将数字m四舍五入到小数点后n位
    SELECT ROUND(123.456,1),ROUND(123.456,2),ROUND(123.456,0);
    
    #n可以不写,默认精确到整数
    SELECT ROUND(123.456);
    
    #n可以为负数,精确到小数点前n位
    SELECT ROUND(126.456,-1),ROUND(173.456,-2),ROUND(823.456,-3);
    
    #truncate(m,n) 将数字m截取到小数点后n位
    SELECT TRUNCATE(123.456,1),TRUNCATE(123.456,2),TRUNCATE(123.456,0);
    
    #truncate必须两个参数都有,不能省略n
    #n可以为负数,截取到小数点前n位
    SELECT TRUNCATE(126.456,-1),TRUNCATE(173.456,-2),TRUNCATE(823.456,-3);
    
    #floor(m) 向下取整,返回小于等于m的最大整数
    #ceil(m) 向上取整,返回大于等于m的最小整数
    SELECT FLOOR(23),FLOOR(23.45),FLOOR(-23.45);
    SELECT CEIL(23),CEIL(23.45),CEIL(-23.45);
    
    #mod(m,n) 计算m除以n的余数
    SELECT MOD(12,5),MOD(123.45,5.7),MOD(12,0);
    
    #rand() 生成一个0到1之间的随机数
    SELECT RAND();
    #要得到一个1到10之间的随机整数
    SELECT ROUND(1+RAND()*9);
    

    2.字符函数

    #concat(str1,str2,...,strN) 将多个字符串连接在一起
    SELECT CONCAT('abcdefg','xyz');
    SELECT CONCAT(ename,job) FROM emp;
    SELECT CONCAT(ename,' is a ',job) FROM emp;
    
    #length(str) 计算字符串的长度
    SELECT LENGTH('abcdefg');
    SELECT ename,LENGTH(ename) FROM emp;
    
    #函数处理过后的数据也可以写在where子句中作为条件
    SELECT * FROM emp
    WHERE LENGTH(ename)=4;
    
    #left(str,n) 截取字符串最左边n个字符
    #right(str,n) 截取字符串最右边n个字符
    SELECT ename,LEFT(ename,2),RIGHT(ename,2) FROM emp;
    
    #mid(str,m,n) 从字符串的第m个字符开始截取长度为n的字符串
    SELECT ename,MID(ename,2,3) FROM emp;
    
    #n可以不写,默认截取后面所有的字符
    SELECT ename,MID(ename,3) FROM emp;
    
    #m可以为负数,从右向左数第m个字符开始截取
    SELECT ename,MID(ename,-2) FROM emp;
    
    #replace(str1,str2,str3) 在str1中找到str2替换为str3
    SELECT REPLACE('He love you','He','I');
    SELECT ename,REPLACE(ename,'A','XXXXX') FROM emp;
    

    3.日期函数

    #日期的格式是'YYYY-MM-DD'
    #时间的格式是'HH:MM:SS'
    
    #查询1981年6月之前入职的员工信息
    SELECT * FROM emp
    WHERE hiredate < '1981-06-01';
    
    #curdate() 返回当前系统日期,curtime 返回当前系统时间
    SELECT CURDATE(),CURTIME();
    
    #now() 返回当前系统日期+时间
    SELECT NOW();
    
    #year(date) 返回日期所在的年份,month(date) 返回日期所在的月份,day(date)返回日期的天数
    SELECT *,YEAR(hiredate),MONTH(hiredate),DAY(hiredate) FROM emp;
    
    #查看冬天入职的员工
    SELECT * FROM emp
    WHERE MONTH(hiredate) IN (10,11,12);
    
    #DATE_ADD(date,interval n 单位) 给日期加上n个单位时间,单位可以是year,month,day
    SELECT DATE_ADD(CURDATE(),INTERVAL -5 MONTH);
    

    4.逻辑函数

    #if(条件判断,value1,value2) 如果条件成立则返回value1,如果条件不成立则返回value2
    #对员工的工资进行判断,员工工资大于等于3000的显示高富帅,其他显示矮矬穷
    SELECT *,IF(sal>=3000,'高富帅','矮矬穷') FROM emp;
    
    #对员工的工资进行判断,员工工资大于等于3000的显示高富帅,
    #2000到3000之间的显示中产
    #1000到2000之间显示小资
    #1000以下矮矬穷
    SELECT *,IF(sal>=3000,'高富帅',IF(sal>=2000,'中产',IF(sal>=1000,'小资','矮矬穷'))) FROM emp;
    
    #ifnull(x,y) 如果x的值为空,则返回y,如果x不为空则返回x
    SELECT *,12*(sal+IFNULL(comm,0)) nianshouru FROM emp;
    
    /*
    case x
    when value1 then result1
    when value2 then result2
    ...
    when valueN then resultN
    else resultN+1
    end
    
    判断x的值,如果x=value1则返回result1
          如果x=value2则返回result2
          ……
          如果x=valueN则返回resultN
          如果以上值都不满足返回resultN+1
    */
    #根据员工不同的职位涨不同幅度的工资
    #clerk涨10%,salesman涨15%
    #manager涨20%,其他人不变
    SELECT *,
    CASE job
    WHEN 'CLERK' THEN sal*1.1
    WHEN 'SALESMAN' THEN sal*1.15
    WHEN 'MANAGER' THEN sal*1.2
    ELSE sal
    END addsal
    FROM emp;
    
    【作业】
    1.用一个SQL语句完成在字符串”hello”左右各添加5个*,
    使其最终返回*****hello*****(用多种方法实现)
    SELECT CONCAT('*****','hello','*****');
    SELECT RPAD(LPAD('hello',10,'*'),15,'*');
    
    2.写一条SQL语句返回”abcdefg”的后三位字符“efg”(用多种方法实现)
    SELECT RIGHT('abcdefg',3);
    SELECT MID('abcdefg',-3);
    SELECT MID('abcdefg',LENGTH('abcdefg')-2);
    
    #trim(str1 from str2) 将str1从str2的两端删除
    #可以添加leading/trailing/both both可以不写,默认从两边删除
    SELECT TRIM(LEADING 'abcd' FROM 'abcdefg');
    
    3.查询emp表,显示删除掉第一个字符后的员工姓名
    (如员工ALLEN,显示为LLEN)(多种方法实现)
    SELECT ename,MID(ename,2) FROM emp;
    SELECT ename,RIGHT(ename,LENGTH(ename)-1) FROM emp;
    
    SELECT ename,TRIM(LEADING LEFT(ename,1) FROM ename) FROM emp;
    
    4.查询emp表,显示姓名中不包含字符’A’的员工信息
    #locate(),position(),instr()
    SELECT ename,INSTR(ename,'A') FROM emp;
    
    SELECT * FROM emp
    WHERE INSTR(ename,'A') = 0;
    
    5.查询emp表,使用员工姓名的第一个字符将员工姓名从左边补齐到长度为10
    SELECT LPAD(ename,10,LEFT(ename,1)) FROM emp;
    
    6.查询emp表,显示下半年入职的员工信息
    SELECT * FROM emp
    WHERE MONTH(hiredate)>6;
    
    7.查询在周一入职的员工信息
    SELECT * FROM emp
    WHERE WEEKDAY(hiredate)='MONDAY';
    
    8.写一条SQL语句查询员工编号、员工姓名、工资、部门号,
    要求当员工在10号部门时,显示’财务部’,20号部门时显示’研发部’,
    30号部门时显示’销售部’,其余部门显示’未知部门’
    SELECT empno,ename,sal,deptno,
    CASE deptno
    WHEN 10 THEN '财务部'
    WHEN 20 THEN '研发部'
    WHEN 30 THEN '销售部'
    ELSE '未知部门'
    END deptname
    FROM emp;
    

    第五章 多表查询

    1.笛卡尔积

    #查询员工的信息和其所在部门的信息
    SELECT * FROM emp;
    SELECT * FROM dept;
    
    SELECT ename,job,sal,dname,loc FROM emp,dept;
    
    #集合A中的所有元素和集合B中的所有元素,组成的有序对成为笛卡尔积,记作A×B
    #在关系型数据库中,多表查询时如果没有连接条件,会产生笛卡尔积
    #连接条件就是两张表之间数据的关系,是A表中的某几列和B表中的某几列数据的联系
    #连接条件写在where子句中,通常为:表1.列1=表2.列2
    #多表查询本质是先生成笛卡尔积,再在笛卡尔积中筛选满足条件的数据
    #查询n张表,至少要有n-1个连接条件
    

    2.多表查询的语法规范

    #多表查询时,必须使用表名来限定所有列名,表名.列名
    #1是为了避免重名的列报错
    #2是为了提高查询效率
    SELECT emp.ename,emp.job,emp.sal,emp.deptno,dept.dname,dept.loc FROM emp,dept;
    
    #多表查询时,给表起别名,再使用表的别名来限定列名
    #表的别名尽量简单,用一个字母能够区分多个表就可以
    #多表查询时,先写from,from单独占一行
    SELECT e.ename,e.job,e.sal,e.deptno,d.dname,d.loc
    FROM emp e,dept d;
    
    #多表查询时,如果查询结果中有同名的列,起不同的别名加以区分
    SELECT e.ename,e.job,e.sal,e.deptno eno,d.deptno,d.dname,d.loc
    FROM emp e,dept d;
    

    3.等值连接

    #两张表之间数据的关系是相等关系
    #通常是指主键和外键的对应
    
    #查询员工的信息和其所在部门的信息
    SELECT e.ename,e.job,e.sal,e.deptno eno,d.deptno,d.dname,d.loc
    FROM emp e,dept d
    WHERE e.deptno = d.deptno;
    
    #如果多表查询时还有其他的普通限定条件,也写在where子句中,用and和连接条件连接
    #查询工资高于2000的员工信息以及其所在的部门信息
    SELECT e.*,d.deptno dno,d.dname,d.loc
    FROM emp e,dept d
    WHERE e.deptno = d.deptno
    AND e.sal > 2000;
    

    4.不等值连接

    SELECT * FROM salgrade;
    
    #查询员工的信息和其所在的工资等级
    SELECT e.*,s.*
    FROM emp e,salgrade s
    WHERE e.sal BETWEEN s.losal AND s.hisal;
    

    5.自连接

    #如果一张表的数据内部有联系,主键和外键在同一张表
    #要将这样的关系体现出来使用自连接
    #首先将一张表看作是两张表,再将两张表的主键和外键进行对应
    #给同一张表起不同的别名,用不同的别名代表不同的表
    
    #查询emp表中员工的姓名和其上级的姓名
    SELECT w.ename,m.ename manager
    FROM emp w,emp m
    WHERE w.mgr = m.empno;
    

    6.外连接

    #在多表查询中,有的数据不满足连接条件,在内连接中是无法显示
    #如果要显示这样的数据,使用外连接
    #如果要显示左边表中不满足连接条件的数据,使用左外连接:left outer join
    #如果要显示右边表中不满足连接条件的数据,使用右外连接:right outer join
    
    #查询emp表中员工的姓名和其上级的姓名,没有上级的员工也显示
    SELECT w.ename,m.ename manager
    FROM emp w LEFT OUTER JOIN emp m
    ON w.mgr = m.empno;
    
    #查询员工信息和部门信息,没有员工的部门也显示
    SELECT e.*,d.deptno dno,d.dname,d.loc
    FROM emp e RIGHT OUTER JOIN dept d
    ON e.deptno = d.deptno;
    
    #全外连接full outer join,mysql暂时不支持
    
    【练习】
    1.查询EMP、DEPT表,输出的列包含员工姓名、工资、部门编号、部门名称、部门地址.
    SELECT e.ename,e.sal,d.deptno,d.dname,d.loc
    FROM emp e,dept d
    WHERE e.deptno = d.deptno;
    
    2.查询工资等级为3/4/5级的员工姓名,工资,工资等级
    SELECT e.ename,e.sal,s.grade
    FROM emp e,salgrade s
    WHERE e.sal BETWEEN s.losal AND s.hisal
    AND s.grade > 2;
    
    3.显示职位是CLERK的员工姓名,工资,工资等级,部门名称
    SELECT e.ename,e.job,e.sal,s.grade,d.dname
    FROM emp e,dept d,salgrade s
    WHERE e.deptno = d.deptno
    AND e.sal BETWEEN s.losal AND s.hisal
    AND e.job = 'CLERK';
    
    4.查询emp表,显示员工姓名及其经理的姓名,没有经理的员工也需要显示
    SELECT w.ename,m.ename manager
    FROM emp w LEFT OUTER JOIN emp m
    ON w.mgr = m.empno;
    
    5.列出EMP表中部门名称和这些部门的员工信息,同时列出那些没有员工的部门
    SELECT d.dname,e.*
    FROM emp e RIGHT OUTER JOIN dept d
    ON e.deptno = d.deptno;
    

    第六章 多行函数

    1.多行函数

    #针对多行数据进行运算,只得到一个结果,就是多行函数
    #又称为分组函数,或聚合函数
    
    #sum() 求和
    SELECT SUM(sal) FROM emp;
    
    #avg() 求平均值
    SELECT AVG(sal) FROM emp;
    
    #sum和avg都只能对数字进行运算
    
    #count() 计数(行数)
    SELECT COUNT(ename) FROM emp;
    SELECT COUNT(*) FROM emp;
    
    #max() 最大值,min() 最小值
    SELECT MAX(sal),MIN(sal) FROM emp;
    SELECT MAX(hiredate),MIN(hiredate) FROM emp;
    SELECT MAX(ename),MIN(ename) FROM emp;
    
    #分组函数在计算时会忽略空值
    SELECT AVG(comm),COUNT(comm) FROM emp;
    SELECT SUM(comm)/14,SUM(comm)/4 FROM emp;
    
    #如果要考虑空值,使用ifnull转换
    SELECT AVG(IFNULL(comm,0)) FROM emp;
    
    #可以使用where子句去限定分组函数计算的范围
    #找出职位是salesman的员工的最高工资
    SELECT MAX(sal) FROM emp
    WHERE job = 'SALESMAN';
    
    #找出10号部门的平均工资
    SELECT AVG(sal) FROM emp
    WHERE deptno = 10;
    
    #oracle中普通列和分组函数是不能直接一起查询的
    #mysql虽然允许这样的语句执行,但是结果没有意义
    #select ename,count(sal) from emp;
    

    2.group BY子句

    #查询每个部门的平均工资
    SELECT deptno,AVG(sal) FROM emp
    GROUP BY deptno;
    
    #select后面既有普通列又有分组函数时,必须写group by子句
    #并且出现在select后面的普通列必须也在group by后面
    
    #查询每个职位的人数
    SELECT job,COUNT(*) FROM emp
    GROUP BY job;
    
    #可以多列分组
    #查询每个部门各个职位的最低工资
    SELECT deptno,job,MIN(sal) FROM emp
    GROUP BY deptno,job;
    

    3.having子句

    #查询部门人数多于5人的部门编号
    /*
    select deptno,count(*) from emp
    where count(*) > 5
    group by deptno;
    
    where子句中不能出现分组函数
    */
    #要对分组函数的结果进行限定,使用having子句
    #having必须在group by后面
    #使用group by可以不用having,但是使用having必须使用group by
    SELECT deptno,COUNT(*) FROM emp
    GROUP BY deptno
    HAVING COUNT(*) > 5;
    
    【练习】
    #1.查询每个职位的职位名称及平均工资,按平均工资升序排列.
    SELECT job,AVG(sal) FROM emp
    GROUP BY job
    ORDER BY AVG(sal);
    #2.查询每个部门的各个职位的平均工资,并按部门编号升序、平均工资降序排序
    SELECT deptno,job,AVG(sal) FROM emp
    GROUP BY deptno,job
    ORDER BY deptno,AVG(sal) DESC;
    3.查询每个工资等级所对应的人数
    SELECT s.grade,COUNT(e.ename)
    FROM emp e,salgrade s
    WHERE e.sal BETWEEN s.losal AND s.hisal
    GROUP BY s.grade;
    4.查询EMP表,要求写一条SQL语句统计出如下图所示结果
          10号部门人数           20号部门人数      30号部门人数
         ------------          ------------     ------------
            3                      5                 6
    SELECT SUM(deptno=10) dept10,
          SUM(deptno=20) dept20,
          SUM(deptno=30) dept30 FROM emp;
    SELECT sal>2000 FROM emp;
    

    第七章 子查询

    #查询工资高于allen的员工信息
    SELECT sal FROM emp
    WHERE ename = 'ALLEN';
    
    SELECT * FROM emp
    WHERE sal > 1600;
    
    #当查询语句的条件不是客观数据,而是表中的数据时,使用子查询
    #子查询又叫做嵌套查询,将一个查询的结果作为另一个查询的条件
    #子查询写在主查询中,必须使用括号表示运算顺序
    SELECT * FROM emp
    WHERE sal > 
    (SELECT sal FROM emp WHERE ename = 'ALLEN') ;
    
    #习惯上,将子查询写在比较运算的右边,而且子查询单独占一行
    #主查询中作为条件的列,必须和子查询的结果数据类型一致
    

    1.单行子查询

    #子查询的结果如果是一行一列数据,就是单行子查询
    
    #查询跟allen的部门和职位都一样的员工信息
    SELECT * FROM emp
    WHERE deptno =
    (SELECT deptno FROM emp WHERE ename = 'ALLEN')
    AND job =
    (SELECT job FROM emp WHERE ename = 'ALLEN');
    
    #主查询和子查询的数据可以不在同一张表
    #查询allen所在的部门名称
    1)多表查询
    SELECT d.dname
    FROM emp e,dept d
    WHERE e.deptno = d.deptno
    AND e.ename = 'ALLEN';
    #多表查询先生成笛卡尔积,再在笛卡尔积中找满足条件的数据
    #一共找了14*4=56次
    
    2)子查询
    SELECT dname FROM dept
    WHERE deptno =
    (SELECT deptno FROM emp WHERE ename = 'ALLEN');
    #先执行子查询,找了14次,再在主查询中查询,找了4次
    #一共找了14+4=18次
    
    #子查询的效率高于多表查询
    #如果查询结果来自多张表,只能使用多表查询
    #如果查询结果来自一张表,只是用到另一张表的数据作为条件
    #可以用子查询也可以用多表查询,推荐使用子查询
    
    #子查询中可以使用分组函数
    #查询emp表中工资最高的员工姓名
    SELECT ename FROM emp
    WHERE sal =
    (SELECT MAX(sal) FROM emp);
    
    #having子句中可以使用子查询
    #查询部门的平均工资高于所有员工平均工资的部门
    SELECT deptno,AVG(sal) FROM emp
    GROUP BY deptno
    HAVING AVG(sal) >
    (SELECT AVG(sal) FROM emp);
    

    2.多行子查询

    #子查询的结果如果是多行一列数据,就是多行子查询
    #多行子查询必须使用多行比较运算符
    
    #in 匹配多个值
    #查询工资大于等于3000的员工所在的部门名称
    SELECT dname FROM dept
    WHERE deptno IN
    (SELECT DISTINCT deptno FROM emp WHERE sal >= 3000);
    
    #any,多个条件满足其中任意一个就可以返回结果
    #查询工资高于任意一个部门的平均工资的员工信息
    SELECT * FROM emp
    WHERE sal > ANY
    (SELECT AVG(sal) FROM emp GROUP BY deptno);
    #大于any表示大于最小值,小于any表示小于最大值
    
    #all,多个条件必须全部满足才能返回结果
    SELECT * FROM emp
    WHERE sal > ALL
    (SELECT AVG(sal) FROM emp GROUP BY deptno);
    #大于all表示大于最大值,小于all表示小于最小值
    

    3.多列子查询

    #子查询的结果如果是多行多列数据,就是多列子查询
    #in 匹配多列的值
    
    #查询跟allen的部门和职位都一样的员工信息
    SELECT * FROM emp
    WHERE (deptno,job) IN
    (SELECT deptno,job FROM emp WHERE ename = 'ALLEN');
    #主查询中列的数量、顺序以及数据类型必须和子查询中的列一致
    
    #子查询的结果可以看作是一张表,再进行查询
    #此时子查询写在from后面,必须起别名
    SELECT * FROM
    (SELECT ename,job,sal,comm,12*sal nianxin,sal+IFNULL(comm,0) yongjin FROM emp) e
    WHERE yongjin > 2000;
    
    #先用一个查询语句构造出一张表,再和其他表做多表查询
    
    【作业】
    1.使用子查询,找出哪个部门下没有员工
    SELECT * FROM dept
    WHERE deptno NOT IN
    (SELECT DISTINCT deptno FROM emp);
    
    2.使用子查询,列出领导是BLAKE的所有员工
    SELECT * FROM emp
    WHERE mgr =
    (SELECT empno FROM emp WHERE ename = 'BLAKE');
    
    3.使用子查询,列出在NEW York工作的员工信息
    SELECT * FROM emp
    WHERE deptno IN
    (SELECT deptno FROM dept WHERE loc = 'NEW YORK');
    
    4.使用子查询,找出那些工资低于平均工资的员工
    SELECT * FROM emp
    WHERE sal <
    (SELECT AVG(sal) FROM emp);
    
    5.使用子查询,找出那些工资低于任意一个部门的平均工资的员工
    SELECT * FROM emp
    WHERE sal < ANY
    (SELECT AVG(sal) FROM emp GROUP BY deptno);
    
    6.使用SQL语句查出各个部门工资最高的员工的部门编号、员工姓名及其工资的信息
    SELECT deptno,ename,sal FROM emp
    WHERE (deptno,sal) IN
    (SELECT deptno,MAX(sal) FROM emp GROUP BY deptno);
    
    7.列出所有部门的相应信息和部门人数,没有员工的部门则部门人数显示为0
    1)多表查询
    SELECT d.*,COUNT(e.ename)
    FROM emp e RIGHT OUTER JOIN dept d
    ON e.deptno = d.deptno
    GROUP BY d.deptno,d.dname,d.loc;
    2)子查询+多表查询
    #部门信息在dept表可以直接查询
    #部门人数不在任何一张表,但是可以通过emp表算出来
    #先使用查询语句计算出部门人数,再将该结果看作一张表跟dept表做多表查询
    
    SELECT deptno,COUNT(ename) ct FROM emp
    GROUP BY deptno;
    
    SELECT d.*,IFNULL(c.ct,0)
    FROM dept d LEFT OUTER JOIN
    (SELECT deptno,COUNT(ename) ct FROM emp
    GROUP BY deptno) c
    ON d.deptno = c.deptno;
    
    SELECT sal FROM emp
    WHERE deptno = 40;
    
    SELECT AVG(sal) FROM emp
    WHERE deptno = 40;
    
    SELECT COUNT(sal) FROM emp
    WHERE deptno = 40;
    
    8.查询高于自己部门平均工资的员工名字,部门号,工资,平均工资(保留2位小数)
    #先使用查询语句计算出每个部门的平均工资
    
    SELECT deptno,AVG(sal) average FROM emp
    GROUP BY deptno;
    
    SELECT e.ename,e.deptno,e.sal,ROUND(a.average,2)
    FROM emp e,
    (SELECT deptno,AVG(sal) average FROM emp
    GROUP BY deptno) a
    WHERE e.deptno = a.deptno
    AND e.sal > a.average;
    

    第八章 集合操作

    #集合操作是指,将查询结果看作是一个集合,集合与集合之间可以做集合操作
    #集合操作:合集、交集、差集、补集
    #mysql中只支持合集操作,union,union all
    #集合操作的效率高于条件组合的查询效率
    #进行集合操作的查询语句,查询的列必须一致
    
    SELECT ename,job,sal,deptno FROM emp
    WHERE deptno = 20
    UNION
    SELECT ename,job,sal,deptno FROM emp
    WHERE sal < 2000;
    
    #union all会显示重复数据
    SELECT ename,job,sal,deptno FROM emp
    WHERE deptno = 20
    UNION ALL
    SELECT ename,job,sal,deptno FROM emp
    WHERE sal < 2000;
    

    相关文章

      网友评论

        本文标题:mysql数据库小知识----查询语言DQL

        本文链接:https://www.haomeiwen.com/subject/tloxzhtx.html