MySQL基础(3)

MySQL索引
概念
  • 索引就是快速查询数据的数据结构
  • 类似于书中的目录, 通过目录就可以快速查找到想要查看的内容
  • 分类
    • 单列索引: 表中的一个字段作为索引列
    • 组合索引: 表中的多个字段作为索引列
    • 普通索引
    • 唯一索引
  • 创建索引的注意点
    • 不能随意创建索引, 索引也是保存到mysql数据表中, 占存储空间
    • 插入,修改,更新数据 索引也是需要进行维护的, 如果索引太多, 维护会很复杂
    • where条件中经常使用的字段可以创建对应的索引
    • 查询过程中查询速度比较慢可以创建索引
  • 索引的优缺点
    • 优点:提高查询效率
    • 缺点:降低增删改效率
索引操作
# 创建索引
# 方式一: create (unique) index 索引名 on 表名 (列名1 排序方式, 列名2 排序方式, ...)
# 向category表中以cname字段创建对应索引
CREATE INDEX idx_cname ON category (cname);

# 方式二: 通过修改表结构添加索引
# alter table 表名 add index 索引名 (列名1 排序方式, 列名2 排序方式, ...)
# 向products表中以price字段创建对应索引
ALTER TABLE products
    ADD INDEX idx_price (price DESC);

# 方式三: 创建表时,创建索引
CREATE TABLE category2
(
    cid   VARCHAR(20) PRIMARY KEY,
    cname VARCHAR(200),
    INDEX idx_cname (cname) -- 创建索引
);

# 删除索引
# 方式一: DROP INDEX 索引名 ON 表名;
DROP INDEX idx_cname ON category2;
# 方式二: ALTER TABLE 表名 DROP INDEX 索引名;
ALTER TABLE products
    DROP INDEX idx_price;

# 展示索引
SHOW INDEX FROM category;

# 索引信息存储在mysql库中的innodb_index_stats表中
SELECT *
FROM
    mysql.innodb_index_stats
WHERE
      database_name = 'bigdata_db'
  AND table_name = 'category'
  AND index_name = 'idx_cname';
事务
  1. MySQL三种引擎
  • 默认innodb是支持事务的
  • 事务要么全成功,要么全失败
  1. 事务功能
  • 用于管理insert,update,delete

  • 回滚到事务开始前的状态

  1. 事务的特点
  • 原子性
  • 一致性
  • 隔离性
  • 持久性

开始事务:begin

事务提交:commit

事务回滚:rollback

窗口函数
  • 分组聚合
# 统计各部门总工资金额, 查询字段部门id, 总金额
SELECT
    deptid,
    SUM(salary) total_salary
FROM
    employee
GROUP BY
    deptid;
  • 开窗函数:组内分组,组内排序
  • 只能对聚合函数开窗
  • 语法: 开窗函数 over(partition by 分组字段1, 分组字段2, … order by 排序字段1 排序方式, …)
  • 窗口规定结果表的数据行, 不会改变结果表的条目数
  • partition by: 将分组聚合的结果添加到各组的数据后
  • order by: 对各组的数据进行排序
  • MySQL5.0版本:定义变量,循环实现
# 使用场景: 查询各组的第一名的数据信息,  统计各组员工的工资占总工资的比例

# 统计各部门总工资金额,并且查询部门中每个人的所有信息
# PARTITION BY: 分组 类似与group by
SELECT *,
       SUM(salary) OVER () total_salary, -- 所有人的总工资
       AVG(salary) OVER () avg_salary,    -- 所有人的平均工资
        avg(salary) OVER (PARTITION BY deptid)  dept_avg_salary, -- 各部门平均工资
        avg(salary) OVER (PARTITION BY deptid order by salary DESC)  dept_avg_salary -- 各部门平均工资, 根据工资字段对各组数据进行排序
FROM
    employee;

# 查询所有员工信息
SELECT *
FROM
    employee;
# 查询所有员工的总工资
SELECT
    SUM(salary) total_salary
FROM
    employee;
    
# 多表连接实现开窗函数需求 
# 交叉连接
SELECT *
FROM
    employee, (SELECT
                   SUM(salary) total_salary
               FROM
                   employee) total;

小结:

  • sum(),结合group by,over,括号内case when/if
  • select sum()与select sum() over ()区别
    • sum()是对表中某一字段求和,结果只有一个值
    • sum() over () 也是对全表的某一个字段求和,结果有一列值(都是最大值)
    • sum想要实现sum over的效果 可以笛卡尔积
  • group by 某个字段之后也可以对其他字段分组后求和select 字段,sum(其他字段)
  • 想对全表计数或求和,count/sum() over ()
  • group by 将字段相同的分成一组
  • TOPN代码实现
# 开窗函数实现查询各组TOPN
/*
实现步骤:
第一步: 通过开窗函数,计算一个各组排序之后的序号列, 结果表中有一列是序号列
第二步: 查询结果表,过滤序号列=1(最大/最小), <=3(前三/后三名)
*/
/*
row_number(): 序号列的值连续不重复 1,2,3,4,5
rank(): 序号列的值重复不连续 1,2,2,4,4,6
dense_rank(): 序号列的值重复且连续 1,2,2,3,4,4,5
*/
# 生成带有序号列的结果表
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY deptid ORDER BY salary DESC) row_rk,
       RANK() OVER (PARTITION BY deptid ORDER BY salary DESC)       rk,
       DENSE_RANK() OVER (PARTITION BY deptid ORDER BY salary DESC) dense_rk
FROM
    employee;

# 根据结果表中的序号列进行过滤, 获取TOPN数据
SELECT *
FROM
    (SELECT *,
            ROW_NUMBER() OVER (PARTITION BY deptid ORDER BY salary DESC) row_rk,
            RANK() OVER (PARTITION BY deptid ORDER BY salary DESC)       rk,
            DENSE_RANK() OVER (PARTITION BY deptid ORDER BY salary DESC) dense_rk
     FROM
         employee) temp
WHERE
    row_rk = 1;
case when语法
  • 基本语法
select
case 
    when 条件 then 返回的值(列名)
    when 条件 then 返回的值(列名)
    ...
    else 返回的值(列名)
end as 列别名
from 表名
  • 使用场景
    • 对某列/某些列进行判断,生成一列新的类别列
# - 需求: 创建一个报表,统计员工的经验水平
# - 显示字段:`first_name`, `last_name`, `hire_date`, 和 `experience`
# - 经验字段(`experience` ):
#   - `'junior'`  2014年1月1日以后雇用的员工
#   - `'middle'` 在2013年1月1日之后至2014年1月1日之前雇用的员工
#   - `'senior'` 2013年1月1日或之前雇用的员工
SELECT
    first_name,
    last_name,
    hire_date,
    CASE
        WHEN hire_date >= '2014-01-01' THEN 'junior'
        WHEN hire_date >= '2013-01-01' AND hire_date < '2014-01-01' THEN 'middle'
        WHEN hire_date < '2013-01-01' THEN 'senior'
        END experience
FROM
    employees;
SELECT
    first_name,
    last_name,
    hire_date,
    CASE
        WHEN hire_date >= '2014-01-01' THEN 'junior'
        WHEN hire_date >= '2013-01-01' AND hire_date < '2014-01-01' THEN 'middle'
        ELSE 'senior'
        END experience
FROM
    employees;

小结:

case when 可以自定义分组
group by 根据某个字段不同值分组
group by 可以使用case when自定义分组,如果要输出分组后的计算值,case when还要在select里写一遍
case when 可以和聚合函数组合使用
group by 和聚合函数count 和 case when/if 组合使用可以对group by分组后的成员进一步分组,group by 分组以某一字段不同行呈现,count(if/case when)以不同列(字段)呈现
case when … then … when … then …else… end 可以给不同自定义的分组和该列起别名
count(case when … then …else … end) ,count(if(判断条件,成立,不成立)) 可以创建多个列
聚合函数,case when ,开窗函数都可以创建列
将count变为sum then后面不能用主键字段名 要改成1
count中不计数的用null,sum中不计数的用0

group by分组sum聚合后可以使用聚合的函数或别名排序
注:count中不计数不能用0
涉及到不同值的累加,SUM不能通过COUNT计数替代
case when 里面也可以使用聚合函数
1.条件分支,匹配条件的返回一个值
2.添加新列,自定义分组
3.group by子句根据case when分组,select也必须含有同样的case when分组
4.在COUNT()或SUM()函数内使用CASE WHEN来创建业务对象的自定义计数

mysql函数
  • 函数: 实现特定功能的代码段

  • 使用函数可以快速的实现计算

    • sum() 求和
  • 经常使用的函数

    • 字符串函数

      • 字符串拼接:concat
      • 指定字符拼接:concat_ws
      • 格式化:format()
      • 替换:replace
      • 截取字符串:substr/substring
      • 从第几个分隔符开始截取:substring_index
    • 日期函数

      • 两个日期作差:datediff
      • date_sub
      • date_add
      • 按表达式要求显示日期:date_format
      • last_date
      • 返回当天日期:curdate
      • 返回当前年月日时分秒:current_time /now
      • 字符串转日期:str_to_time
    • 数值函数

      • 最大:max
      • 最小:min
      • 求和:sum
      • 计数:count
      • 平均值:avg
      • 四舍五入保留小数位:round
      • 绝对值:abs
      • 整除:div
      • 向上取整:ceil
      • 向下取整:floor
      • 一行数据的最大值:greatest
      • 取余:mod
    • 其他函数

      • case

      • if

      • ifnull

sql执行语句的顺序

select 查询内容

from 表

where 分组前的条件

group by 分组字段

having 分组后的条件

order by 排序字段

limit [m,]n

from > where > group by > 函数计算 > having > select > order by > limit 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值