MySQL 基础篇 二【DQL:数据库查询语言】

DQL查询:

 

一、基础查询

1、查询字段:

2、查询常量、表达式、函数

 3、起别名

3、去重

4、加号的作用与字符串拼接函数:concat();

二、条件查询

三、排序查询

四、常见函数

五、分组函数

六、分组查询

 按表达式或函数分组,以及总结:

七、连接查询

七*、SQL99语法 的内外链接

 1.等值连接

2.非等值连接

3.自连接

 外连接

5.交叉连接

八、子查询

1.标量子查询

2.列子查询(多行子查询)

3.放在select后的子查询

4.放在exists后的子查询

九、分页查询

十、union联合查询


一、基础查询

1、查询字段:

SHOW DATABASES;
#基础查询
/*
语法:
select 查询列表 from 表名;
特点:
查询列表可以是表中的字段,常量值、表达式、函数
查询结果是一个虚拟的表格
*/

#先启用指定的库:
USE myemployees;

#1.查询表中单个字段

SELECT last_name FROM employees;

#2.查询表中的多个字段
#为了防止字段和关键字重名,可以加上着重号:``
SELECT `last_name`,`salary`,`email` FROM employees;

#3、查询表中的所有字段
# 如果用*,那么查询顺序和表中一样。
SELECT * FROM employees;

#运行:先选中,然后F9即可

 查询结果:(后文略)

2、查询常量、表达式、函数

#4.查询常量值

SELECT 100;
#sql中不区分字符和字符串,都用单引号即可。
SELECT 'john';

#5.查询表达式
SELECT 100%98;

#6.查询函数
SELECT VERSION();

 

 3、起别名

#7.起别名
#方式一:便于理解,如果要查询的字段有重名的情况,使用别名可以区分开。
SELECT 100%98 AS 结果;
SELECT last_name AS 姓 FROM employees;

#方式二:使用空格
SELECT last_name 姓 FROM employees;

#案例:查询salary,显示结果为 out put 这里Out put中间有特殊符号空格,所以建议加上双引号
SELECT salary AS "out put" FROM employees;

 

3、去重

去掉重复字段:

#8.去重

#案例:查询员工表中涉及到的所有部门编号
SELECT DISTINCT department_id FROM employees;

4、加号的作用与字符串拼接函数:concat();

#+号的作用
-- java中的+号
-- 1、运算符,两个操作数都为数值型
-- 2、连接符,只要有一个操作数为字符串
-- 
-- MySQL中,只有一个功能:运算符
-- select 100+90;这就是加法。
-- 两个操作数为数值型,做加法运算;
-- select '123' +90,有其中一方为字符型,试图将字符型数值转换成数值型
-- 如果转换成功,则继续做加法运算;
-- 如果转换失败,如select 'john' +90
-- 则将字符型数值转换成0,然后继续加。
-- 这里答案是90.
-- 
-- 如果其中一方为Null,不管另一方是什么,则结果肯定为Null.
如果要字符串拼接,使用concat函数。如下:
CONCAT('a','b','c') AS 结果;

#案例:查询员工名和姓,连接成一个字段,并显示为 姓名
SELECT CONCAT(last_name,first_name) AS 姓名 FROM employees;

 

二、条件查询

总体框架:

进阶2:条件查询


语法:
SELECT 查询列表 FROM 表名 WHERE 筛选条件;


分类:
1、按条件表达式筛选
条件运算符:> < =  <> >= <=


2、按逻辑表达式筛选
逻辑运算符: && || !
AND OR NOT


3、模糊查询
LIKE 
BETWEEN AND
IN
IS NULL

-- 一 按条件表达式筛选
-- 查询工资大于12000的员工信息

SELECT * FROM employees WHERE salary>12000;

-- 案例2:查询部门编号不等于90号的员工名和部门编号
SELECT 
last_name,department_id 
FROM 
employees 
WHERE 
department_id <> 90;

按逻辑表达式筛选
查询工资在10000到20000之间的员工名、工资以及奖金

SELECT 
last_name,salary,commission_pct
FROM
employees
WHERE
salary>=10000 AND salary<=20000;

案例2 查询部门编号不是在90到110之间,或者工资高于15000的员工信息
SELECT
*
FROM
employees
WHERE
NOT(department_id>=90 AND department_id<=110) OR salary>15000;

 模糊查询:

三、模糊查询
LIKE
BETWEEN AND
IN
IS NULL
IS NOT NULL
1.like

案例 查询员工名中包含字符a的员工信息
SELECT 
*
FROM 
employees
WHERE
last_name LIKE '%a%';

百分号代表任意位置,a的前面可能有字符,也可能后面有字符

案例2 查询员工中第三个字符为e,第五个字符为a的员工名和工资
前面单个字符用下划线代替
SELECT
last_name,
salary
FROM
employees
WHERE
last_name LIKE '__e_a%';

案例3 查询员工名中第二个字符为_的员工名

SELECT
last_name
FROM
employees
WHERE
last_name LIKE '_\_%';
在需要的字符前面加上\即可转义。

2、 BETWEEN AND
查询员工编号在100到120之间的员工信息
SELECT
*
FROM
employees
WHERE
employee_id BETWEEN 100 AND 120;

可以提高语句简洁度

两个临界值需要升序。

3、in关键字
查询员工的工种编号是 IT_PROG、AD_VP AD_PRES中的一个员工名和工种编号
SELECT
last_name,
job_id
FROM 
employees
WHERE
job_id = 'IT_PROT' OR job_id = 'AD_VP' OR job_id = 'AD_PRES';

SELECT
last_name,
job_id
FROM 
employees
WHERE
job_id IN ('IT_PROT','AD_VP','AD_PRES');

特点:1.提高语句简洁度
2.in列表的值必须一致或兼容
3.不支持模糊搜索,不能用%或者_

4.is NULL

案例:查询没有奖金的员工名和奖金率
SELECT
last_name,
commission_pct
FROM
employees
WHERE
commission_pct IS NULL;

有的话,就是 IS NOT NULL;

=或<>不能用于判断null值

三、排序查询

排序查询

语法:
SELECT 查询列表
FROM 表
【where 筛选条件】
ORDER BY 排序列表 ASC|DESC


案例 查询员工信息,要求工资从高到低排序
SELECT 
* 
FROM 
employees
ORDER BY
salary DESC;

默认升序

案例2 查询部门编号大于等于90的员工信息,按入职时间的先后进行排序
SELECT
*
FROM
employees
WHERE
department_id >=90
ORDER BY
hiredate ASC;

案例3 按表达式排序 按年薪的高低显示员工信息和年薪
SELECT 
*,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY 
salary*12*(1+IFNULL(commission_pct,0)) DESC;

案例4 按年薪的高低显示员工的信息和年薪 【按别名排序】
SELECT *,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY 
年薪;

案例5:按姓名的长度显示员工的姓名和工资【按函数排序】
SELECT LENGTH(last_name) AS 字节长度,last_name,salary
FROM employees
ORDER BY 字节长度 DESC;

案例6:查询员工信息,要求先按工资排序,再按员工编号排序【按多个字段排序】
SELECT
*
FROM
employees
ORDER BY
salary ASC,employee_id ASC;

ORDER BY 字句可以支持单个字段,多个字段,表达式,函数,别名
ORDER BY 字句一般放在查询语句的最后面,limit字句除外

案例:查询员工的姓名和部门号和年薪,按年薪降序,按姓名升序
SELECT
last_name,department_id,salary*12*(1+IFNULL(commission_pct,0)) AS 年薪
FROM
employees
ORDER BY
年薪 DESC,last_name ASC;

四、常见函数

一、单行函数

    1、字符函数

        concat拼接

        substr截取子串

        upper转换成大写

        lower转换成小写

        trim去前后指定的空格和字符

        ltrim去左边空格

        rtrim去右边空格

        replace替换

        lpad左填充

        rpad右填充

        instr返回子串第一次出现的索引

        length 获取字节个数

       

    2、数学函数

        round 四舍五入

        rand 随机数

        floor向下取整

        ceil向上取整

        mod取余

        truncate截断

    3、日期函数

        now当前系统日期+时间

        curdate当前系统日期

        curtime当前系统时间

        str_to_date 将字符转换成日期

        date_format将日期转换成字符

    4、流程控制函数

        if 处理双分支

        case语句 处理多分支

            情况1:处理等值判断

SELECT salary AS 原始工资,department_id,
CASE department_id
WHEN 30 THEN salary*1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工资
FROM employees;

 

            情况2:处理条件判断       

    5、其他函数

        version版本

        database当前库

        user当前连接用户

五、分组函数

        sum 求和

        max 最大值

        min 最小值

        avg 平均值

        count 计数

        特点:

        1、以上五个分组函数都忽略null值,除了count(*)

        2、sum和avg一般用于处理数值型 max、min、count可以处理任何数据类型

        3、都可以搭配distinct使用,用于统计去重后的结果

        4、count的参数可以支持:

            字段、*、常量值,一般放1

           建议使用 count(*)

练习:

1.查询公司员工工资的最大值,最小值,平均值,总和
SELECT
MAX(salary) mx_sal,
MIN(salary) xi_sal,
ROUND(AVG(salary),2) ag_sal,
SUM(salary) sm_sal
FROM
employees;

round保留2位小数

2.查询员工表中的最大入职时间和最小入职时间的相差天数

SELECT DATEDIFF(MAX(hiredate),MIN(hiredate));

3.查询部门编号为90的员工个数
SELECT COUNT(*) 个数
FROM employees
WHERE department_id = 90;

六、分组查询

1.查询每个工种的最高工资
SELECT 
MAX(salary),job_id
FROM 
employees
GROUP BY
job_id;

2.查询每个位置上的部门个数
SELECT COUNT(*),location_id
FROM 
departments
GROUP BY
location_id;

添加筛选条件
1.查询邮箱中包含a字符的,每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
WHERE email LIKE '%a%'
GROUP BY department_id;

案例2:查询有奖金的每个领导手下员工的最高工资
SELECT
MAX(salary),manager_id
FROM
employees
WHERE
commission_pct IS NOT NULL
GROUP BY
manager_id;

添加复杂筛选条件
1.查询哪个部门的员工个数>2
1 查询每个部门的员工个数
2 筛选出大于2的部门
having用于分组后的筛选
SELECT
department_id,COUNT(*)
FROM
employees
GROUP BY
department_id
HAVING COUNT(*)>2;
 
 案例2:查询每个工种有奖金的员工的最高工资>12000的工种编号和最高工资
 1 查询每个工种有奖金的员工的最高工资
 SELECT 
 MAX(salary),job_id
 FROM
 employees
 WHERE
 commission_pct IS NOT NULL
 GROUP BY
 job_id;
 
 2 根据1的结果继续筛选,最高工资>12000
 SELECT 
 MAX(salary),job_id
 FROM
 employees
 WHERE
 commission_pct IS NOT NULL
 GROUP BY
 job_id
 HAVING
 MAX(salary)>12000;
 
 案例3:查询领导编号>102的每个领导手下的最低工资>5000的领导编号
 以及其最低工资 
 
 SELECT
 MIN(salary),manager_id
 FROM
 employees 
 WHERE
 manager_id >102
 GROUP BY
 manager_id
 HAVING
 MIN(salary)>5000;
 
 
分组查询的筛选条件分为两类
数据源不一样

分组前筛选:原始表 使用where 在 GROUP BY 前面
分组后筛选:分组后的结果集 使用having 在 GROUP BY 后面

分组函数做条件肯定是放在having子句中
能用分组前筛选的,就优先考虑分组前。

 按表达式或函数分组,以及总结:

按表达式或函数分组
案例:按员工姓名长度分组
查询每一组的员工个数,筛选员工个数大于5的有哪些
SELECT 
COUNT(*),LENGTH(last_name) len_name
FROM
employees
GROUP BY
LENGTH(last_name)
HAVING
COUNT(*) >5;

按多个字段分组
案例:查询每个部门每个工种的员工的平均工资
SELECT 
AVG(salary),department_id,job_id
FROM
employees
GROUP BY
department_id,job_id;

#添加排序
案例 查询每个部门每个工种的员工的平均工资,
并按照平均工资的高低显示
SELECT AVG(salary),department_id,job_id
FROM
employees
GROUP BY
job_id,department_id
ORDER BY AVG(salary) DESC;

GROUP BY 子句支持单个字段分组,多个字段分组,
多个字段用逗号隔开没有顺序要求,表达式或函数(用的较少)
也可以添加排序(放在最后)

练习:
1.查询各job_id的员工工资的最大值,最小值,平均值,总和,并按照job_id升序
SELECT MAX(salary),MIN(salary),AVG(salary),SUM(salary),job_id
FROM employees
GROUP BY job_id
ORDER BY job_id ASC;

2.查询员工最高工资和最低工资的差距
SELECT MAX(salary)-MIN(salary) difference
FROM employees;

3.查询各个管理者手下员工的最低工资,其中最低工资不能低于6000,
没有管理者的员工不计算在内
SELECT MIN(salary),manager_id
FROM employees
WHERE manager_id IS NOT NULL
GROUP BY manager_id
HAVING MIN(salary)>=6000;

4.查询所有部门的编号,员工数量和工资平均值,并按照平均工资降序
SELECT department_id,COUNT(*),AVG(salary)
FROM employees
GROUP BY department_id
ORDER BY AVG(salary) DESC;

5.选择具有各个job_id的员工人数
SELECT COUNT(*),job_id
FROM employees
WHERE job_id IS NOT NULL
GROUP BY job_Id;

七、连接查询

含义:又称多表查询

笛卡尔乘积现象
表1有m行,表2有n行
结果有m*n行

发生原因:没有有效的连接条件
如何避免:添加有效的连接条件

SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id = boys.id;

记得加作用域!

分类:
按年代分类:SQL 92仅仅支持内连接  
SQL 99 支持内连接+外连接(左右)+交叉连接

按功能分类:

内连接:

等值连接
非等值连接
自连接

外连接:
左外连接
右外连接
全外连接

交叉连接

1、等值连接

1.等值连接
案例1 查询女神名和对应男神名
SELECT NAME,boyName FROM boys,beauty
WHERE beauty.boyfriend_id = boys.id;


USE myemployees;
#案例2 查询员工名和对应的部门名
SELECT last_name,department_name
FROM employees,departments
WHERE employees.`department_id` = departments.`department_id`;

2.查询员工号,工种号,工种名
SELECT last_name,employees.job_id,job_title
FROM employees,jobs
WHERE employees.`job_id` = jobs.`job_id`;

3.查询有奖金的员工名,部门名
使用AND加筛选

SELECT last_name,department_name,commission_pct
FROM employees e,departments d
WHERE e.department_id = d.department_id
AND e.commission_pct IS NOT NULL;

案例2 查询城市名中第二个字符为o的部门名和城市名
SELECT department_name,city
FROM departments d,locations l
WHERE d.location_id = l.location_id
AND l.city LIKE '_o%';

是否能加分组?
案例1:查询每个城市的部门个数
SELECT COUNT(*),city
FROM departments d,locations l
GROUP BY city;

案例2 查询有奖金的每个部门的部门名和部门的领导编号,和该部门的最低工资
SELECT department_name,d.manager_id,MIN(salary)
FROM departments d,employees e
WHERE d.department_id = e.department_id
AND commission_pct IS NOT NULL
GROUP BY department_name,d.manager_id;

三表连接:
案例 查询员工名,部门名和所在城市
SELECT 
e.last_name,d.department_name,l.city
FROM
employees e,departments d,locations l
WHERE
e.department_id = d.department_id
AND
d.location_id = l.location_id;

2、非等值连接

把同一张表当成两张表使用

查询员工的工资和工资级别

SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.lowest_Sal AND g.highest_sal;

 3.自连接

案例:查询员工名和上级的名称

七*、SQL99语法 的内外链接

语法:
SELECT 查询列表
FROM 表1 别名[连接类型]
JOIN 表1 别名[连接类型]
ON 连接条件
【where 筛选条件】
【group BY 分组】
【having 筛选条件】
【order BY 排序列表】

分类:
内连接:inner
左外连接:left OUTER 
右外连接:right OUTER
全外连接:full OUTER
交叉连接:cross 

 1.等值连接

1 等值连接

案例一 查询员工名,部门名
SELECT last_name,department_name
FROM employees e 
INNER JOIN departments d
ON e.department_id = d.department_id;

案例二 查询名字中包含e的员工名和工种名(筛选)
SELECT last_name,job_title
FROM employees e
INNER JOIN jobs j
ON e.job_id = j.job_id
WHERE last_name LIKE '%e%';

案例三 查询部门个数>3的城市名和部门个数(添加分组和筛选)
SELECT COUNT(*),city,department_id
FROM departments d
INNER JOIN locations l
ON d.location_id = l.location_id
GROUP BY city
HAVING COUNT(*) > 3;

案例4 查询哪个部门的员工个数>3的部门名和员工个数,并按个数降序
SELECT e.department_id,department_name,COUNT(*)
FROM departments d
INNER JOIN employees e
ON d.department_id = e.department_id
GROUP BY department_name
HAVING COUNT(*) > 3
ORDER BY COUNT(*) DESC;

案例5 查询员工名、部门名、工种名,并按部门名降序
SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d ON e.department_id = d.department_id
INNER JOIN jobs j ON e.job_id = j.job_id
ORDER BY d.department_name DESC;

2.非等值连接

查询员工工资级别

SELECT salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal;

查询工资级别>2的个数,并且按工资级别降序
SELECT COUNT(*),salary,grade_level
FROM employees e
INNER JOIN job_grades g
ON e.salary BETWEEN g.lowest_sal AND g.highest_sal;
GROUP BY grade_level
HAVING COUNT(*) >20
ORDER BY grade_level DESC;

3.自连接

自连接
查询员工名字,上级的名字
SELECT e.last_name,m.last_name
FROM employees e
INNER JOIN employees m
ON e.manager_id = m.employee_id;

 外连接

外连接用于查询一个表中有,一个表中没有的情况。

有主表和从表

外连接的查询记录为主表中的所有记录

从表中有匹配的,就匹配

无匹配的,就成为NULL

外连接结果 = 内连接结果+主表中有而从表中没有的记录。

左外连接:主表left join从表

右外连接:从表right join主表

左外和右外交换顺序可实现同样效果。

外连接
引入 查询男朋友不在男神表的女神名

USE girls;

外连接用于查询一个表中有,一个表中没有的情况

引入 查询男朋友不在男神表的女神名
SELECT b.name,boys.*
FROM beauty b
LEFT OUTER JOIN boys
ON b.boyfriend_id = boys.id;

USE myemployees;

案例1 查询哪个部门没有员工
左外
SELECT d.department_name,employee_id
FROM departments d
LEFT OUTER JOIN employees e
ON d.department_id = e.department_id
WHERE e.employee_id IS NULL;

右外
SELECT d.department_name,employee_id
FROM employees e
RIGHT OUTER JOIN departments d
ON d.department_id = e.department_id
WHERE e.employee_id IS NULL;

4.全外连接

5.交叉连接

也就是笛卡尔乘积。 

八、子查询

出现在其他语句中的select语句,称为子查询或内查询
外部的查询语句,称为主查询

示例:

分类:
按子查询出现的位置:
select后面
仅仅支持标量子查询
from后面
表子查询
where或者having后面【重要】
标量子查询,
列子查询,
行子查询

exists后面(相关子查询)
表子查询

按结果集的行列数不同
标量子查询:结果集只有一行一列
行子查询:结果集有一行多列
列子查询:结果集只有一列多行
表子查询:结果集一般为多行多列
 

1.标量子查询

一.where或者having后
1.标量子查询

特点:
1.子查询放在小括号内
2.子查询一般放在条件的右侧
3.标量子查询,一般搭配着单行操作符使用
4.列子查询,一般搭配着多行操作符使用

标量子查询
案例一:谁的工资比阿贝尔高?
1.查询阿贝尔的工资
USE myemployees;
SELECT salary
FROM employees
WHERE last_name = 'Abel';

SELECT last_name
FROM employees
WHERE salary>(SELECT salary
FROM employees
WHERE last_name = 'Abel');

案例2 返回job_id与141号员工相同,salary比143号员工多的员工 姓名,job_id和工资
SELECT job_id
FROM employees
WHERE employee_id = 141;

SELECT salary
FROM employees
WHERE employee_id = 143;

SELECT last_name,job_id,salary
FROM employees
WHERE 
job_id = (SELECT job_id
FROM employees
WHERE employee_id = 141)
AND
salary>(SELECT salary
FROM employees
WHERE employee_id = 143);

案例3:返回公司工资最少的员工的信息
SELECT last_name,job_id,salary
FROM employees
WHERE salary =(SELECT MIN(salary)
FROM employees) ;

2.列子查询(多行子查询)


一列多行

案例1:返回location_id是1400或1700的部门中所有员工姓名
1.先查location_id是1400或1700的部门编号
SELECT department_id
FROM departments
WHERE location_id = 1400 OR location_id = 1700;

2.再查询姓名,要求部门号是1中某一个
SELECT last_name
FROM employees
WHERE department_id IN
(SELECT department_id
FROM departments
WHERE location_id = 1400 OR location_id = 1700);

3.返回其他部门中比job_id为 IT_PROG 部门任一工资低的员工的员工号,姓名,job_id以及salary
SELECT salary
FROM employees
WHERE job_id ='IT_PROG';

SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ANY
(SELECT DISTINCT salary
FROM employees
WHERE job_id ='IT_PROG')AND job_id<>'IT_PORG';

4.返回其他部门中比job_id为 IT_PROG 部门所有工资低的员工的员工号,姓名,job_id以及salary
SELECT employee_id,last_name,job_id,salary
FROM employees
WHERE salary<ALL
(SELECT DISTINCT salary
FROM employees
WHERE job_id ='IT_PROG')AND job_id<>'IT_PORG';

3.放在select后的子查询

4.放在exists后的子查询

看子查询后有无值

(in的方式)

(exists的方式)

九、分页查询

应用场景:

 

    实际的web项目中需要根据用户的需求提交对应的分页查询的sql语句

 

语法:

 

    select 字段|表达式,...

    from 表

    【where 条件】

    【group by 分组字段】

    【having 条件】

    【order by 排序的字段】

    limit 【起始的条目索引,】条目数;

特点:

    1.起始条目索引从0开始

   

    2.limit子句放在查询语句的最后

   

    3.公式:select * from  表 limit (page-1)*sizePerPage,sizePerPage

    假如:

    每页显示条目数sizePerPage

    要显示的页数 page

案例1 查询前五条员工信息

SELECT *
FROM employees
LIMIT 0,5;

案例2 查询第11条~第25条
SELECT *
FROM employees
LIMIT 10,15;

案例3 有奖金的员工信息,并且工资较高的前10名显示出来
SELECT * 
FROM employees
WHERE commission_pct IS NOT NULL
ORDER BY salary DESC
LIMIT 0,10; 

特点:
1.limit语句放在查询语句最后
2.公式:
要显示的页数是page
每页条目数是size
SELECT 查询列表 FROM 表
LIMIT (page-1)*size,size;

十、union联合查询

引入:

    union 联合、合并

语法:

    select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】

    select 字段|常量|表达式|函数 【from 表】 【where 条件】 union 【all】

    select 字段|常量|表达式|函数 【from 表】 【where 条件】 union  【all】

    .....

    select 字段|常量|表达式|函数 【from 表】 【where 条件】

特点:

    1、多条查询语句的查询的列数必须是一致的

    2、多条查询语句的查询的列的类型几乎相同

    3、union代表去重,union all代表不去重

联合查询
UNION 联合,合并 将多条查询语句的结果合并成一个结果
引入的案例:查询部门编号大于90或者邮箱中包含a的员工信息

SELECT *
FROM employees
WHERE email LIKE '%a%'
UNION
SELECT *
FROM employees
WHERE department_id>90;

应用场景
查询中国用户中男性的信息以及外国用户中男性的信息
SELECT id,cname,csex
FROM t_ca
WHERE csex = '男'
UNION
SELECT t_id,tName,tGender
FROM t_ua
WHERE tGender = 'male';

猜你喜欢

转载自blog.csdn.net/Kukeoo/article/details/114215843
今日推荐