SQL综合练习

知识点回顾

根据对RDBMS赋予的指令种类的不同,SQL语句可以分为以下三类

  • DDL

DDL(Data Definition Language,数据定义语言) 用来创建或者删除存储数据用的数据库以及数据库中的表等对象。DDL 包含以下几种指令:

1)CREATE:创建数据库和表等对象

2)DROP:删除数据库和表等对象

3) ALTER:修改数据库和表等对象的结构

  • DML

DML(Data Manipulation Language,数据操纵语言) 用来查询或者变更表中的记录。DML 包含以下几种指令:

1) SELECT:查询表中的数据

2)INSERT:向表中插入新数据

3)UPDATE:更新表中的数据

4)DELETE:删除表中的数据

  • DCL

DCL(Data Control Language,数据控制语言) 用来确认或者取消对数据库中的数据进行的变更。除此之外,还可以对 RDBMS 的用户是否有权限操作数据库中的对象(数据库表等)进行设定。DCL 包含以下几种指令:

1)COMMIT:确认对数据库中的数据进行的变更

2)ROLLBACK:取消对数据库中的数据进行的变更
3)GRANT:赋予用户操作权限

4)REVOKE:取消用户的操作权限

一、搭框架

数据库的创建

create database <数据库名称>;

使用该数据库

use <数据库名称>;

创建表格

create table <表名>
( <列名 1> < 数据类型 > < 该列所需约束 >,
  <列名 2> < 数据类型 > < 该列所需约束 >,
  ·
  ·
  ·
  primary key (作为主键的列名));

表的删除【注意:删除的表无法恢复,只能重新插入!!!

drop table < 表名 >;

添加一个新的列

alter table <表名>
add column
< 列的定义 >;

删除列

alter table < 表名 > drop column <列名>;

清空表的内容(速度比 drop / delete更快 )

truncate table < 表名 >;

数据的更新

update < 表名 >
set < 列名 > = < 表达式 > [, < 列名2 > = < 表达式2 >……]/null;
where < 条件 >; -- 可选
order by 子句; -- 可选
limit 子句; --可选

向表中插入数据

insert into < 表名 > (1, 列2, 列3,……) values
(1,2,3,……);

二、SELECT

select < 列名 >,
  from < 表名 >
  where < 条件表达式 >;

① SQL中常用比较运算符

运算符含义
=和……相等
<>和……不相等 (not 也可以表示否定)
>=大于等于
>大于
<=小于等于
<小于

② select distinct 列名

可以删除这个列中重复的数据

③ 希望选取null记录时,需要在条件表达式中使用 is null 运算符;

​ 希望选取不是null记录时,需要在条件表达式中使用is not null运算符。

④ SQL 中用于汇总的函数叫做聚合函数,以下五个师最常用的聚合函数:

函数名功能
COUNT计算表中的记录数(行数)
SUM计算表中数值列中数据的合计值
AVG计算表中数值列中数据的平均值
MAX求出表中任意列中数据的最大值
MIN求出表中任意列中数据的最小值

聚合函数会将 NULL 排除在外,但COUNT(*)除外,它会得到包含NULL的数据行数;而COUNT(<列名>)会得到NULL之外的数据行数

三、GROUP BY 语句

将现有的数据按照某列来汇总统计

select <列名1>,<列名2>,<列名3>,……
from <表名>
group by <列名1>,<列名2>,<列名3>,……;

① 会将NULL作为一组特殊数据进行处理

② select 后面出现的除了聚合函数的列之外,只能是group by 子句后面出现的列名

四、HAVING语句

在使用group by 进行分组后,再使用having语句对分组进行过滤,可以使用数字、聚合函数和GROUP BY中指定的列名。

五、ORDER BY语句

当SQL执行的结果需要按照特定顺序排序时,可以使用order by 语句

select <列名1>,<列名2>,<列名3>,……
  from <表名>
  order by <排序基准列1>,<排序基准列2>,……

默认为升序 ASC,降序排列为DESC

六、视图

创建视图

create view <视图名称><列名1>,<列名2>,……)
as 
<select 语句>

修改视图

alter view <视图名>
as
<select 语句>

注: 如果包含以下结构的任意一种都是不可以被更新的:

聚合函数 SUM()、MIN()、COUNT()等
DISTINCT关键字
GROUP BY子句
HAVING子句
UNION或UNION ALL运算符
FROM 子句中包含多个表

删除视图(需要有相应的权限才能成功删除)

drop view <视图名1>[,<视图名2>……]

七、各种函数

算术函数

  • abs(数值)

用于计算一个数字的绝对值,表示一个数到原点的距离

当参数为null时,返回值也是null

  • mod(被除数,除数)

计算除法余数(求余),只能对整数列求余数

  • round(对象数值,保留小数的位数)

用来进行四舍五入操作

注意:当参数 保留小数的位数 为变量时,可能会遇到错误

字符串函数

  • concat( str1, str2, str3 )

进行拼接

  • length( 字符串 )

求字符串的长度

  • lower( 字符串 )

把字符串中的字母都换成小写

  • upper( 字符串 )

把字符串中的字母都换成大写

  • replace( 对象字符串,替换前的字符串,替换后的字符串 )
  • substring( 对象字符串 FROM 截取的起始位置 FOR 截取的字符数)

使用 SUBSTRING 函数 可以截取出字符串中的一部分字符串。截取的起始位置从字符串最左侧开始计算,索引值起始为1。

  • substring_index( 原始字符串,分隔符,n)

该函数用来获取原始字符串按照分隔符分割后,第 n 个分隔符之前(或之后)的子字符串,支持正向和反向索引,索引起始值分别为 1 和 -1。

日期函数( select )

  • current_date

获取当前日期

  • current_time

当前时间

  • current_timestamp

当前日期和时间

  • extract(日期元素 from 日期)

截取日期元素(年、月、小时、秒)

该函数的返回值并不是日期类型而是数值类型

转换函数

  • cast( 转换前的值 as 想要转换的数据类型 )
  • coalesce( 数据1,数据2,数据3……)

该函数会返回从左侧开始第1个不是null的值

谓词

  • like

like ‘ddd%’ 前方一致:代表以ddd开头的所有字符串

like ‘%ddd%’ 中间一致:查询对象字符串中含有作为查询条件的字符串,无论该字符串出现在字符串的前面、中间还是最后

like ‘%ddd’ 后方一致:作为查询条件的字符串与查询对象字符串的末尾部分相同

使用_下划线来代替%,并且1个下划线代表1个字符

  • between

用于范围查询

between a and b 结果是闭区间,包含a,b这两个临界值

  • is null、is not null

用于判断是否为null

  • or

多个查询条件取并集时可以选择使用or语句

也可以用 (not) in(值1,值2,值3……)来替换

CASE 表达式

类似于if else的功能!!!

case when <求值表达式> then <表达式>
	 when <求值表达式> then <表达式>
	 when <求值表达式> then <表达式>
	 ·
	 ·
	 ·
else <表达式>
end

① 一般写在select里

② 可以写sum(case when then end )

集合运算

  • union

表的加法,通常会除去重复的记录

  • union all

保留重复行

  • except

表的减法,不支持哦,一般可以用not in

  • except all

不支持哦

  • 对称差

不支持哦,但是可以通过a-b 并 b-a

  • 连结

1)inner join

-- 内连结
FROM <tb_1> INNER JOIN <tb_2> ON <condition(s)>

注:select 子句中的列最好按照 表名.列名 的格式来使用

2)natural join

SELECT *  FROM shopproduct NATURAL JOIN product

3)外连结

-- 左连结     
FROM <tb_1> LEFT  OUTER JOIN <tb_2> ON <condition(s)>
-- 右连结     
FROM <tb_1> RIGHT OUTER JOIN <tb_2> ON <condition(s)>
-- 全外连结
FROM <tb_1> FULL  OUTER JOIN <tb_2> ON <condition(s)>

窗口函数

<窗口函数> OVER ([PARTITION BY <列名>]
                     ORDER BY <排序用列名>)  

PARTITON BY是用来分组,即选择要看哪个窗口,类似于GROUP BY 子句的分组功能,但是PARTITION BY 子句并不具备GROUP BY 子句的汇总功能,并不会改变原始表中记录的行数。

ORDER BY是用来排序,即决定窗口内,是按那种规则(字段)来排序的。

1)专用窗口函数

  • rank函数

(1,1,1,4)

  • dense_rank函数

(1,1,1,2)

  • row_number函数

(1,2,3,4)

2)聚合函数

出来的结果是一个累计的聚合函数值

sum avg max min

3)移动平均

# PRECEDING(“之前”), 将框架指定为 “截止到之前 n 行”,加上自身行
<窗口函数> OVER (ORDER BY <排序用列名>
                 ROWS n PRECEDING )  
# FOLLOWING(“之后”), 将框架指定为 “截止到之后 n 行”,加上自身行         # BETWEEN 1 PRECEDING AND 1 FOLLOWING,将框架指定为 “之前1行” + “之后1行” + “自身”        
<窗口函数> OVER (ORDER BY <排序用列名>
                 ROWS BETWEEN n PRECEDING AND n FOLLOWING)

4)rollup

在 group by 后面使用with rollup不仅可以得到每个分类的小计,而且还可以得到分类的总计

书写位置

select (窗口函数) ⇒ \Rightarrow from ⇒ \Rightarrow join ⇒ \Rightarrow where ⇒ \Rightarrow group by ⇒ \Rightarrow having ⇒ \Rightarrow order by

执行顺序

from ⇒ \Rightarrow join ⇒ \Rightarrow where ⇒ \Rightarrow group by ⇒ \Rightarrow having ⇒ \Rightarrow select ⇒ \Rightarrow 窗口函数 ⇒ \Rightarrow order by ⇒ \Rightarrow limit

练习一:各部门工资最高的员工(难度:中等)

创建Employee 表,包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。

±—±------±-------±-------------+
| Id | Name | Salary | DepartmentId |
±—±------±-------±-------------+
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
±—±------±-------±-------------+
创建Department 表,包含公司所有部门的信息。

±—±---------+
| Id | Name |
±—±---------+
| 1 | IT |
| 2 | Sales |
±—±---------+
编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。

±-----------±---------±-------+
| Department | Employee | Salary |
±-----------±---------±-------+
| IT | Max | 90000 |
| Sales | Henry | 80000 |
±-----------±---------±-------+

【解答】
首先创建两张表,在创建表时需要注意:

  1. Name 是字符,在插入表中这一列的值时,要加引号;
  2. 一般都把 Id 设置为字符型,插入时也要用引号哦~
-- 创建表Employee
create table Employee
( Id varchar(4) ,
  Name varchar(15),
  Salary integer,
  DepartmentId varchar(4), 
  primary key (Id));
  -- 插入数据
  insert into Employee 
  values
  ('1', 'Joe', 70000, '1'),
  ('2', 'Henry', 80000, '2'),
  ('3', 'Sam', 60000, '2'),
  ('4', 'Max', 90000, '1');
 -- 创建表Department
  create table Department
  (Id varchar(4),
   Name varchar(20),
   primary key(Id));
   -- 插入数据
   insert into Department
   values
   ('1', 'IT'),
   ('2', 'Sales');

在这里插入图片描述
在这里插入图片描述
先把薪资由高到低排好序,再与部门表连结~

 select b.Name as Department, a.Name as Employee, a.Salary
  from
  (select  Salary, Name, DepartmentId,
  rank () over (partition by DepartmentId order by Salary DESC) as ranking
  from Employee) a 
  join Department as b
  on a.DepartmentID = b.Id
  where a.ranking = 1;

在这里插入图片描述

练习二: 换座位(难度:中等)

小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。

其中纵列的id是连续递增的

小美想改变相邻俩学生的座位。

你能不能帮她写一个 SQL query 来输出小美想要的结果呢?

请创建如下所示seat表:

示例:

±--------±--------+
| id | student |
±--------±--------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
±--------±--------+
假如数据输入的是上表,则输出结果如下:

±--------±--------+
| id | student |
±--------±--------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
±--------±--------+
注意:
如果学生人数是奇数,则不需要改变最后一个同学的座位。

【解答】
上面想要的就是相邻两个学生互换!
先创建表

-- 创建表seat
create table seat
(id varchar(10),
 student varchar(20),
 primary key(id));
 -- 插入数据
 insert into seat
 values
 ('1', 'Abbot'),
 ('2', 'Doris'),
 ('3', 'Emerson'),
 ('4', 'Green'),
 ('5', 'Jeames');

在这里插入图片描述
思路:如果学号是奇数,则id+1;如果学号是偶数,则id-1;另外需要特别注意的是,如果学生人数为奇数,最后一个学生的 id 不变
因此在判断时,大体分为三种情况:
① id 为奇数, 且id不是学生总人数 则id+1;
② id 为奇数, 且id为学生总人数 则id不变;
③ id为偶数,则id-1

select seat.student,
(case 
when mod(id,2) != 0 and id != stu_sum then id+1
when mod(id,2) != 0 and id = stu_sum then id
else id-1 end) as id
from seat, (select count(*) as stu_sum from seat) as a
order by id;

在这里插入图片描述
如果不写order by id, 则不会按顺序排!!!(下图不对)
在这里插入图片描述
【答案(思路更加简单一丢丢了)】

select
	(case when id = (select max(id) from seat) then id
		 when mod(id,2) = 1 then id+1
		 when mod(id,2) = 0 then id-1
		 else null end)  as id,
	student
from seat
order by id;

练习三: 分数排名(难度:中等)

编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

创建以下score表:

±—±------+
| Id | Score |
±—±------+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
±—±------+
例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):

±------±-----+
| Score | Rank |
±------±-----+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
±------±-----+
【解答】
创建表并插入数据

create table score
(Id varchar(5),
 Score float
);
insert into score
values
(1, 3.50),
(2, 3.65),
(3, 4.00),
(4, 3.85),
(5, 4.00),
(6, 3.65);

在这里插入图片描述

注:
① 创建表时,如果想某一列为小数可以用decimal(a,b)表示,a表示小数点左右两边总的位数,b表示小数点右边的位数;
② 在select里边要写round来控制最后输出的成绩的小数位数。

select round(Score,2),
dense_rank() over( order by Score DESC) as 'Rank'
from score;

在这里插入图片描述
提醒!!!!!
– 窗口函数
– PARTITION BY 用于分组,不分组时,省略即可
– ORDER BY 用于排序,默认升级,降序使用 DESC关键字
– RANK() 美式排名,跳过式排序,得分相同时排序相同
– DENSE_RANK() 中式排名, 递增式排序,得分相同时排序相同
– ROW_NUMBER() 赋予唯一连续的名次

练习四:连续出现的数字(难度:中等)

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

±—±----+
| Id | Num |
±—±----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
±—±----+
例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。

±----------------+
| ConsecutiveNums |
±----------------+
| 1 |
±----------------+

【解答】

create table Logs
(Id varchar(4),
 Num integer,
 primary key(Id));
 insert into Logs 
 values 
 ('1', 1),
 ('2', 1),
 ('3', 1),
 ('4', 2),
 ('5', 1),
 ('6', 2),
 ('7', 2);
-- 注意需要添加关键字 distinct,因为如果一个数字连续出现超过 3 次,会返回重复元素。
select distinct a.num as ConsecutiveNums
from 
Logs as a,
Logs as b,
Logs as c
where
a.Id = b.Id-1
and b.Id = c.Id-1
and a.Num = b.Num
and b.Num = c.Num;

在这里插入图片描述

练习五:树节点 (难度:中等)

对于tree表,id是树节点的标识,p_id是其父节点的id。

±—±-----+
| id | p_id |
±—±-----+
| 1 | null |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
±—±-----+
每个节点都是以下三种类型中的一种:

Root: 如果节点是根节点。
Leaf: 如果节点是叶子节点。
Inner: 如果节点既不是根节点也不是叶子节点。
写一条查询语句打印节点id及对应的节点类型。按照节点id排序。上面例子的对应结果为:

±—±-----+
| id | Type |
±—±-----+
| 1 | Root |
| 2 | Inner|
| 3 | Leaf |
| 4 | Leaf |
| 5 | Leaf |
±—±-----+
说明

节点’1’是根节点,因为它的父节点为NULL,有’2’和’3’两个子节点。
节点’2’是内部节点,因为它的父节点是’1’,有子节点’4’和’5’。
节点’3’,‘4’,'5’是叶子节点,因为它们有父节点但没有子节点。
下面是树的图形:

1         

/ \
2 3
/
4 5
注意

如果一个树只有一个节点,只需要输出根节点属性。

【解答】
先创建tree表,并插入数据

create table tree
(id varchar(5),
 p_id varchar(10),
 primary key(id));
 insert into tree
 values
 ('1', null),
 ('2', 1),
 ('3', 1),
 ('4', 2),
 ('5', 2);

该题目分为以下几种情况:
① 树只有一个节点 则为根节点;
② p_id 为null 则为根节点;
③ id 中出现的但是没在p_id中出现,即为没有子节点 则为叶节点leaf;
④ 剩余情况则为 inner.

通俗来讲,p_id是爸爸,p_id为空的就是根节点;id是儿子,id为空的就是叶子;其余情况为inner

select distinct a.id,
(case 
when a.p_id is null then 'Root'
when b.id is null then 'Leaf'
else 'Inner' end ) as Type
from tree as a 
left join
tree as b
on a.id=b.p_id
order by id;

在这里插入图片描述

select id,
       (case when p_id is null then 'Root'
       		when id in (select p_id from tree) then 'Inner'
       		else 'Leaf' end) as Type
from tree; 

练习六:至少有五名直接下属的经理 (难度:中等)

Employee表包含所有员工及其上级的信息。每位员工都有一个Id,并且还有一个对应主管的Id(ManagerId)。

±-----±---------±----------±---------+
|Id |Name |Department |ManagerId |
±-----±---------±----------±---------+
|101 |John |A |null |
|102 |Dan |A |101 |
|103 |James |A |101 |
|104 |Amy |A |101 |
|105 |Anne |A |101 |
|106 |Ron |B |101 |
±-----±---------±----------±---------+
针对Employee表,写一条SQL语句找出有5个下属的主管。对于上面的表,结果应输出:

±------+
| Name |
±------+
| John |
±------+
注意:

没有人向自己汇报。

【解答】

create table Employee
(Id char(3),
 Name varchar(10),
 Department varchar(8),
 ManagerId varchar(3),
 primary key(Id));
 
 insert into Employee
 values
 ('101', 'Jojn', 'A', null),
 ('102', 'Dan', 'A', '101'),
 ('103', 'James', 'A' ,'101'),
 ('104', 'Amy', 'A', '101'),
 ('105', 'Anne', 'A', '101'),
 ('106', 'Ron', 'B', '101');
select  a.name as Name
from
Employee as a
left join 
Employee as b
on
a.Id = b.ManagerId
where a.ManagerId is null
group by a.name
having count(b.ManagerId)>=5;

在这里插入图片描述
先把领导和从属员工连结起来,再一个where限制让a表出现的都是领导!!再按照领导分组,统计领导下边的员工数。

练习七: 分数排名 (难度:中等)

练习三的分数表,实现排名功能,但是排名需要是非连续的,如下:

±------±-----+
| Score | Rank |
±------±-----+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 3 |
| 3.65 | 4 |
| 3.65 | 4 |
| 3.50 | 6 |
±------±-----
【解答】
因为是非连续排名,所以需要把练习三的窗口函数修改为rank()

select round(Score,2),
rank() over( order by Score DESC) as 'Rank'
from score;

在这里插入图片描述

练习八:查询回答率最高的问题 (难度:中等)

求出survey_log表中回答率最高的问题,表格的字段有:uid, action, question_id, answer_id, q_num, timestamp。

uid是用户id;action的值为:“show”, “answer”, “skip”;当action是"answer"时,answer_id不为空,相反,当action是"show"和"skip"时为空(null);q_num是问题的数字序号。

写一条sql语句找出回答率最高的问题。

举例:

输入
在这里插入图片描述
输出
在这里插入图片描述
说明

问题285的回答率为1/1,然而问题369的回答率是0/1,所以输出是285。

**注意:**最高回答率的意思是:同一个问题出现的次数中回答的比例。
【解答】
思路:首先明确要group by 问题id,因此要选择问题id;然后计算回答率,分母是这个问题出现了几次(show),分子是这个问题回答了几次(answer),外边再套一个select选出回答率最高的问题。

create table survey_log
(uid varchar(5),
 action varchar(10),
 question_id varchar(5),
 answer_id varchar(10),
 q_num varchar(5),
 timestamp varchar(5));
 
 insert into survey_log
 values
 ('5', 'show', '285', 'null', '1', '123'),
 ('5', 'answer', '285', '124124', '1', '124'),
 ('5', 'show', '369', 'null', '2', '125'),
 ('5', 'skip', '369', 'null', '2', '126');
select question_id as 'survey_log'
from
(select question_id,
sum(case when action = 'answer' then 1 when action = 'skip' then 0 end)/sum(case when action = 'show' then 1 end) as answer_r
from survey_log
group by question_id
having answer_r > 0)a;

在这里插入图片描述
上面有点凑出来的答案的感觉,正确答案 ① 如下所示:

select case when max(a.answer_rate) then question_id end
from 
(
select question_id,
sum(case when action = 'answer' then 1 end)
/ sum(case when action <> 'skip' then 1 end) as answer_rate
from survey_log
group by 1
) a;

在这里插入图片描述

记住!!!case when max ()的用法哦!!!

正确答案②

select a.question_id
from (
 			select question_id,
 					   sum(case when answer_id is not null then 1 else 0 end) / sum(case when action = 'show' then 1 else 0 end) as ratio
 			from survey_log
 			group by question_id
 			order by ratio DESC
 			limit 1) a ;   

练习九:各部门前3高工资的员工(难度:中等)

将项目7中的employee表清空,重新插入以下数据(其实是多插入5,6两行):

±—±------±-------±-------------+
| Id | Name | Salary | DepartmentId |
±—±------±-------±-------------+
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
±—±------±-------±-------------+
编写一个 SQL 查询,找出每个部门工资前三高的员工。例如,根据上述给定的表格,查询结果应返回:

±-----------±---------±-------+
| Department | Employee | Salary |
±-----------±---------±-------+
| IT | Max | 90000 |
| IT | Randy | 85000 |
| IT | Joe | 70000 |
| Sales | Henry | 80000 |
| Sales | Sam | 60000 |
±-----------±---------±-------+
此外,请考虑实现各部门前N高工资的员工功能。

【解答】

 select 
 b.Name as 'Department',
 a.Name as 'Employee',
 a.Salary
 from 
 (select DepartmentId,
		 Name,
         Salary,
         row_number() over
         (partition by DepartmentId order by Salary DESC) as ranking
           from Employee) as a
  join Department as b
  on a.DepartmentId = b.Id
  where a.ranking <= 3;

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值