美文网首页
数据库基本查询和高级查询

数据库基本查询和高级查询

作者: 叩首问路梦码为生 | 来源:发表于2023-03-24 20:27 被阅读0次

    数据库基本查询

    普通查询

    记录查询

    1.最基本的查询语句是由 SELECT 和FROM 关键字组成的

    SEIECT * FROM t emp;
    SELECT empno, ename, sal FROM t emp;
    

    2.SELECT语句屏蔽了物理层的操作,用户不必关心数据的真实存储,交由数据库高效的查找数据

    使用列别名

    1.通常情况下,SELECT子句中使用了表达式,那么这列的名字就默认为表达式,因此需要一种对列名重命名的机制

    SELECT
    empno,
    sal*12 As "income"
    FROM temp;
    

    查询语句的子句执行顺序

    SELECT
    empno,
    sal*12 As "income"
    FROM t emp;
    
    1-> 2-> ->3
    词法分析与优化 FROM SELECT
    读取SQL语句 选择数据来源 选择输出内容

    数据分页

    1.比如我们查看朋友圈,只会加载少量部分信息,不用一次性加载全部朋友圈,那样只会浪费CPU时间、内存和网络带宽
    2.如果结果集的记录很多,则可以使用LIMIT关键字限定结果集数量。

    SELECT......FROM......LIMIT 起始位置,偏移量;

    SELECT empno, ename FROM t_emp LIMIT 0, 20;

    数据分页的简写用法

    1.如果LIMIT子句只有一个参数,它表示的是偏移量,起始值默认为0

    SELECT empno, ename FROM t_emp LIMIT 10;
    SELECT empno, ename FROM t_emp LIMIT 0,10;
    

    执行顺序:FROM -> SELECT -> LIMIT

    排序

    如果没有设置,查询语句不会对结果集进行排序。也就是说,如果想让结果集按照某种顺序排列,就必须使用ORDER BY子句。 以下代码是根据sal 升序
    1.ASC代表升序(默认),DESC代表降序
    2.如果排序列是数字类型,数据库就按照数字大小排序,如果是日期类型就按照日期大小排序,如果是字符串就按照字符集序号排序。

    #SELECT... FROM ...ORDER BY 列名 [ASC I DESC];//ASC 升序(默认)   DESC降序
    SELECT ename, sal FROM t_emp ORDER BY sal;  //升序
    SELECT ename, sal FROM t_emp ORDER BY hiredate DESC //降序
    

    3.我们可以使用ORDER BY规定首要排序条件和次要排序条件。数据库会先按照首要排序条件排序,如果遇到首要排序内容相同的记录
    ,那么就会启用次要排序条件接着排序

    # 优先根据 sal  降序排,其次根据hiredate 升序排
    SELECT empno, ename, sal, hiredate FROM t_emp ORDER BY sal DESC, hiredate ASC
    # 优先根据 deptno升序排,其次根据sal 降序排
    SELECT empno, ename, deptno, sal FROM t_emp ORDER BY deptno, sal DESC
    SELECT empno, ename, sal  FROM t_emp ORDER BY sal DESC LIMIT 0, 5;
    

    去除重复记录

    1.如果我们需要去除重复的数据,可以使用DISTINCT关键字来实现

    #SELECT DISTINCT 字段 FROM ...;
    SELECT DISTINCT job FROM t_emp;
    

    tips:
    1.仅仅是结果集里面显示的 根据job 字段去重
    2.使用DISTINCT的SELECT子句中只能查询一列数据,如果查询多列,去除重复记录就会失效。

    SELECT DISTINCT job, ename FROM t_emp;
    

    条件查询

    1.很多时候,用户感兴趣的并不是逻辑表里的全部记录,而只是它们当中能够满足某一种或某几种条件的记录。这类条件要用WHERE子
    句来实现数据的筛选

    #AND 代表逻辑与,OR代表逻辑或    
    SELECT...FROM...WHERE 条件 [AND IOR]条件
    SELECT empno, ename, sal FROM t_emp WHERE deptno=10 AND sal >= 2000;
    

    2.WHERE语句中的条件运算会用到以下四种运算符:数学运算符、比较运算符、逻辑运笪符、按位运算符

    SELECT deptno,empno,ename,sal 
    FROM t_emp 
    WHERE (deptno=10 OR deptno=20) AND sal>=2000;
    
    #查询部门编号10 ,年薪1.5w以上,工龄20年以上的人员
    SELECT empno,ename,sal,hiredate 
    FROM t_emp 
    WHERE  deptno =10 AND (sal+IFNULL(comm,0))*12>=15000
    AND DATEDIFF(NOW(),hiredate)/365>=20;
    

    3.逻辑运算符
    AND 与关系 age > 18 AND sex = "男"
    OR 或关系 empno = 8000 OR deptno = 20
    NOT 非关系 NOT deptno = 20
    XOR 异或关系 age > 18 xOR sex ="男”
    tips : xor ture+ ture = false , false+false=false , ture + flase =true

    4.WHERE子句的注意事项
    WHERE子句中,条件执行的顺序是从左到右的。所以我们应该把索
    引条件,或者饰选掉记录最多的条件写在最左侧,这样能优化查询速度

    SELECT empno, ename FROM t emp
    WHERE ename = "FORD" AND sal >=2000;
    SELECT empno, ename FROM temp
    WHERE deptno = 10 AND sal >= 2000;
    

    5.各种子句的执行顺序
    条件查询中,WHERE子句应该是第几个执行?
    FROM -> WHERE -> SELECT -> ORDER BY -> LIMIT

    数据库高级查询

    6.聚合函数

    #聚合函数 AVG 求平均值 
    SELECT AVG(sal+IFNULL(comm,0)) AS avg 
    FROM t_emp;
    
    #SUM 求和 
    SELECT SUM(sal) FROM t_emp WHERE deptno IN(10,20);
    
    # MAX求最大值
    SELECT MAX(comm) FROM t_emp;
    SELECT MAx(sal+IFNULL(comm,0)) FROM t_emp 
    WHERE deptno IN (10,20);//查询10和20部门中,月收入最高的员工?
    SELECT MAX(LENGTH(ename)) FROM t_emp;//查询员工名宇最长的是几个字符?
    
    #MIN函数用来获得非值的最小值 
    SELECT MIN(empno) FROM t_emp;
    SELECT MIN(hiredate) FROM t_emp;
    
    #COUNT(*)用于获得包含空值的记录数,COUNT(列名)用于获得包含非空值的记录数。
    SELECT COUNT (*) FROM t emp;
    SELECI COUNT (comm) FROM t emp;
    
    #查询10和20部门中,底薪超过2000元,并且工龄超过15年的员工人数?
    SELECT COUNT(*) FROM t_emp
    WHERE deptno IN(10,20) AND sal>=2000 
    AND DATEDIFF(NOW(),hiredate)/365>=15;
    
    #查询1985年以后入职的员工,底薪超过公司平均底薪的员工数量?
    #这里是查询不出来的,聚合函数AVG 不能出现在where条件语句里面,因为结果集没有查询出来 ,聚合函数需要有结果集才能继续。
    SELECT COUNT(*) FROM t_emp
    WHERE hiredate >="1985-01-01" AND sal>AVG(sal);
    
    

    7.数据库表的分组查询
    默认情况下汇总函数是对全表范围内的数据做统计
    GROUP BY子句的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对每个小区域分别进行数据汇总处理

    #按照部门编号分组,求每组的底薪平均值
    SELECT deptno ,ROUND(AVG(sal))
    FROM t_emp GROUP BY deptno;
    
    #逐级分组 
    #查询每个部门里,每种职位的人员数量和平均底薪 
    SELECT deptno,job,COUNT(*),AVG(sal)
    FROM t_emp GROUP BY deptno,job ORDER BY deptno;
    
    

    8.对SELECT子句的要求
    查询语句中如果含有GROUP BY子句,那么SELECT子句中的内容就必须要遵守规定:SELECT子句中可以包括聚合函数,或者GROUP
    BY子句的分组列,其余内容均不可以出现在SELECT子句中

    SELECT deptno, COUNT (*), AVG (sal)
    FROM t_emp GROUP BY deptno;
    # 下面这条语句查询不出来的原因是 ,结果集 sal 多条 跟count 一条 对应不上
    SELECT deptno, COUNT (*), AVG (sal), sal
    FROM t emp GROUP BY deptno;
    

    9.对分组结果集再次做汇总计算

    SELECT
    deptno, COUNT (*), AVG (sal), MAX (sal), MIN (sal)
    FROM temp GROUP BY deptno WITH ROLLUP;
    

    WITH ROLLUP 分组结果集再次做汇总计算,对列计算,插在最下面一行

    10.GROUP CONCAT函数
    GROUP CONCAT函数可以把分组查询中的某个字段拼接成一个字
    符串

    #查询每个部门内底新超过2000元的人数和员工姓名 , 
    # ename 多条拼接成一条跟count* 对应
    SELECT deptno, COUNT(*),GROUP_CONCAT(ename)
    FROM t_emp WHERE sal>=2000
    GROUP BY deptno;
    

    11.各种子句的执行顺序
    查询语句中,GROUP BY子句应该第几个执行?
    FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT

    12.分组查询遇到的困难?
    以下代码有问题 , where 是优先于group by 执行的,一旦where字句中出现AVG类似的汇总函数,所以MySQL不知道 AVG汇总函数没办法知道按照什么样的范围统计汇总数值
    所以引入HAVING子句来解决这个问题。

    #查询每个部门内底新超过2000元的人数和员工姓名 (此语法错误)
    SELECT deptno, COUNT(*),GROUP_CONCAT(ename)
    FROM t_emp WHERE sal>=2000
    GROUP BY deptno;
    
    #查询每个部门内底新超过2000元的人数和员工姓名 (此语法正确)
    SELECT deptno
    FROM t_emp
    GROUP BY deptno HAVING AVG (sal) >=2000;
    
    1. HAVING子句
    #查询每个部门中,1982年以后入职的员工超过2个人的部门编号 ,通过having子句
    SELECT deptno 
    FROM t_emp
    WHERE hiredate >="1982-01-01"
    GROUP BY deptno HAVING COUNT(*) >=2 AND AVG(sal) >=2000
    ORDER BY deptno ASC;
    

    14.HAVING子句的特殊用法

    SELECT deptno, COUNT(*)
    FROM t_emp
    WHERE  deptno IN (10, 20)
    GROUP BY 1;
    

    15.从多张表中提取数据
    规定了连接条件的表连接语向,就不会出现笛卡尔积

    SELECT e.empno, e.ename, d.dname
    FROM t_emp e JOIN t_dept d
    ON e.deptno=d.deptno;
    

    16.表连接的分类
    内连接是结果集中只保留符合连接条件的记录
    外连接是不管符不符合连接条件,记录都要保留在结果集中

    17.内连接的简介
    内连接是最常见的一种表连接,用于查询多张关系表符合连接条件的记录。
    内连接的多种语法形式

    #以下写法都一样
    SELECT .... FROM 表1 JOIN 表2  ON  连接条件;
    SELECT  … FROM 表1 JOIN  表2  WHERE 连接条件;
    SELECT  … FROM 表1,表2 WHERE 连接条件;
    
    #查询每个员工的工号、姓名、部门名称、底薪、职位、工资等级?(表内连接用法)
    SELECT
    e.empno, e.ename, d.deptno,e.sal,e.job, s.grade
    FROM t_emp e
    JOIN t_dept d ON e.deptno=d.deptno
    JOIN t_salgrade s oN e.sal BETWEEN s.losal AND s.hisal;
    
    #查询与SCOTT相同部门的员工都有谁
    SELECT ename
    FROM t_emp
    WHERE deptno=(SELECT deptno FROM t_emp WHERE ename="SCOTT")
    AND ename!="SCOTT";
    
    #相同的数据表也可以做表连接,用表连接的方式来实现上面的查询,效率更高
    SELECT e2.ename
    FROM t_emp e1 JOIN t_emp e2 ON e1.deptno=e2.deptno
    WHERE e1.ename="SCOTT" AND e2.ename !="SCOTT"
    
    #查询RESEARCH部门的人数、最高底薪、最低底薪、平均底薪、平均工龄?
    SELECT COUNT(*) , MAX(e.sal) , MIN(e.sal) , AVG(e.sal),AVG(DATEDIFF(NOW(),e.hiredate)/365)
    FROM t_emp e JOIN t_dept d ON e.deptno=d.deptno
    WHERE d.dname="RESEARCH";
    
    #查询每种职业的最高工资、最低工资、平均工资、最高工资等级和最低工资等级
    SELECT
    e.job,
    MAX(e.sal+IFNULL(e.comm, 0)),
    MIN(e.sal+IFNULL(e.comm, 0)),
    AVG(e.sal+IFNULL(e.comm, 0)),
    MAX(s.grade) ,
    MIN(s.grade)
    FROM t_emp e JOIN t_salgrade s
    ON (e.sal+IFNULL(e.comm, 0)) BETWEEN s.losal AND s.hisal
    GROUP BY e.job;
    
    #查询每个底薪超过部门平均底薪的员工信息
    SELECT e.empno, e.ename, e.sal
    FROM t_emp e JOIN
    (SELECT deptno, AVG(sal) AS avg FROM t_emp GROUP BY deptno) t
    ON e.deptno=t.deptno AND e.sal>=t.avg;
    
    #左外连接,左表保留所有,右表如果有值出值,没值出null值匹配
    SELECT e.empno, e.ename, d.dname
    FROM t_emp e LEFT JOIN t_dept d
    ON e.deptno=d.deptno;
    
    #右外连接,右表保留所有,左表如果有值出值,没值出null值匹配
    SELECT e.empno, e.ename, d.dname
    FROM t_dept d RIGHT JOIN t_emp e
    ON e.deptno=d.deptno;
    
    #外连接练习1:查询每个部门的名称和部门的人数?
    SELECT d.dname, COUNT(e.deptno)
    FROM t_dept d LEFT JOIN t_emp e
    ON d.deptno=e.deptno
    GROUP BY d.deptno;
    
    #UNION关键字可以将多个查询语句的结果集进行合并
    #(查询语句)UNION(直询语包)UNION(直询语句)
    #查询每个部门的名称和部门的人数?如果没有部门的员工,部门名称用NULL代替。
    (
    SELECT d.dname, COUNT(e.deptno)
    FROM t_dept d LEFT JOIN t_emp e
    ON d.deptno=e.deptno
    GROUP BY d.deptno
    ) UNION
    (SELECT d.dname, COUNT(*)
    FROM t_dept d RIGHT JOIN t_emp e
    ON d.deptno=e.deptno
    GROUP BY d.deptno);
    
    #查询每名员工的编号、姓名、部门、月薪、工资等级、工龄、上司编号、上司姓名、上司部门?
    SELECT
    e.empno, e.ename, d.dname, e.sal+IFNULL(e.comm, 0), s.grade,
    FLOOR(DATEDIFF(NOW(),e.hiredate)/365),
    t.empno AS mgrno, t.ename AS mname, t.dname AS mdname
    FROM t_emp e LEFT JOIN t_dept d ON e.deptno=d.deptno
    LEFT JOIN t_salgrade s ON e.sal BETWEEN s.losal AND s.hisal
    LEFT JOIN
    (SELECT e1.empno, e1.ename, d1.dname
    FROM t_emp e1 JOIN t_dept d1
    ON e1.deptno=d1.deptno
    ) t ON e.mgr=t.empno;
    
    

    内连接总结:内连接的数据表不一定必须有同名字段,只要字段之间符合逻辑关系就可以。
    外连接总结: 左外连接就是保留左表所有的记录,与右表做连接。如果右表有符合条件的记录就与左表连接。如果右表没有符合条件的记录,就用NULL与左表连接。右外连接也是如此。

    18.外连接的注意事项
    内连接只保留符合条件的记录,所以查询条件写在ON子句和
    WHERE子句中的效果是相同的。但是外连接里,条件写在WHERE
    子向里,不合符条件的记录是会被过滤掉的,而不是保留下来。

    SELECT
    e.empno,e.ename, d.dname
    FROM
    t_emp e
    LEFT JOIN t_dept d ON e.deptno = d.deptno
    WHERE e.deptno = 10;
    

    19.子查询的分类
    子查询可以写在三个地方:WHERE子句、FROM子句、SELECT子
    句,但是只有FROM子句子查询是最可取的
    19.1)WHERE子查询(不推荐)
    这种子查询最简单,最容易理解,但是却是效率很低的子查询
    查询底薪超过公司平均底薪的员工的信息

    #WHERE子查询
    SELECT
    empno, ename, sal
    FROM t_emp
    WHERE sal>=(SELECT AVG(sal) FROM t_emp);
    

    19.2)FROM子查询(推荐)
    这种子查询只会执行一次,所以FROM子查询查询效率很高

    #FROM子查询
    SRTECT
    e.empno, e.ename, e.sal,t.avg
    FROM t_emp e JOIN
    (SELECT deptno, AVG (sal) as avg
    FROM t_emp GROUP BY deptno) t
    ON e.deptno=t. deptno AND e.sal>=t.avg;
    

    19.3)SELECT子查询(不推荐)
    这种子查询每输出一条记录的时候都要执行一次,查询效率很低

    #SELECT子查询
    SELECT
    e.empno, e.ename,
    (SELECT dname FROM t_dept WHERE deptno=e.deptno)
    FROM t_emp e;
    

    20.数据操作语言:子查询(二)
    20.1)单行子查询和多行子查询
    单行子查询的结果集只有一条记录,多行子查询结果集有多行记录
    多行子查询只能出现在WHERE子句和FROM子句中

    #如何用子查询查找FORD和MARTIN两个人的同事?
    SELECT ename
    FROM t_emp
    WHERE deptno IN(SELECT deptno FROM t_emp WHERE ename IN("FORD", "MARTIN"))
    AND ename NOT IN("FORD", "MARTIN");
    

    20.2)WHERE子句中的多行子查询
    WHERE子句中,可以使用IN、ALL、ANY、EXISTS关键字来处理多行表达式结果集的条件判断

    #查询比FORD和MARTIN底薪都高的员工信息?
    SELECT ename FROM t_emp
    WHERE sal >= ALL
    (SELECT sal FROM t_emp
    WHERE ename IN ("FORD","MARTIN"))
    AND ename NOT IN ("FORD", "MARTIN");
    
    SELECT ename FROM t_emp
    WHERE sal >= ANY
    (SELECT sal FROM t_emp
    WHERE ename IN ("FORD","MARTIN"))
    AND ename NOT IN ("FORD", "MARTIN");
    

    20.3)EXISTS关键字(存在)
    EXISTS关键宇是把原来在子查询之外的条件判断,写到了子查询的里面。
    SELECT...FROM 表名 WHERE [NOT] EXISTS(子查询);

    #查询工资等级是3级或者4级的员工信息
    SELECT empno, ename, sal
    FROM t_emp
    WHERE EXISTS(
    SELECT grade FROM t_salgrade
    WHERE sal BETWEEN losal AND hisal
    AND grade IN (3, 4)
    );
    
    t_bonus.png
    t_dept.png
    t_emp.png
    t_salgrade.png

    相关文章

      网友评论

          本文标题:数据库基本查询和高级查询

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