Compare commits
2 Commits
1ed786139f
...
cb02a70fcf
Author | SHA1 | Date | |
---|---|---|---|
cb02a70fcf | |||
98b3779e63 |
458
SQL-窗口函数.md
Normal file
458
SQL-窗口函数.md
Normal file
@ -0,0 +1,458 @@
|
||||
# SQL窗口函数
|
||||
|
||||
### 一. 什么是窗口函数
|
||||
|
||||
#### 基本含义
|
||||
|
||||
窗口限定一个范围,它可以理解为满足某些条件的记录集合,窗口函数也就是在窗口范围内执行的函数。
|
||||
|
||||
#### 基本语法
|
||||
|
||||
窗口函数有over关键字,指定函数执行的范围,可分为三部分:分组子句(partition by),排序子句(order by),窗口子句(rows)
|
||||
|
||||
```sql
|
||||
<函数名> over (partition by <分组的列> order by <排序的列> rows between <起始行> and <终止行>)
|
||||
```
|
||||
|
||||
|
||||
|
||||
**注意Mysql8才支持窗口函数**
|
||||
|
||||
|
||||
|
||||
#### 演示表格
|
||||
|
||||
| cid(班级id) | sname(学生姓名) | score(分数) |
|
||||
| ------------ | ----------------- | ------------- |
|
||||
| 001 | 张三 | 78 |
|
||||
| 001 | 李四 | 82 |
|
||||
| 002 | 小明 | 90 |
|
||||
| 001 | 王五 | 67 |
|
||||
| 002 | 小红 | 85 |
|
||||
| 002 | 小刚 | 62 |
|
||||
|
||||
#### 演示脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_5 (
|
||||
cid varchar(4),
|
||||
sname varchar(4),
|
||||
score int
|
||||
);
|
||||
|
||||
insert into SQL_5 (cid, sname, score) values ('001', '张三', 78);
|
||||
insert into SQL_5 (cid, sname, score) values ('001', '李四', 82);
|
||||
insert into SQL_5 (cid, sname, score) values ('002', '小明', 90);
|
||||
insert into SQL_5 (cid, sname, score) values ('001', '王五', 67);
|
||||
insert into SQL_5 (cid, sname, score) values ('002', '小红', 85);
|
||||
insert into SQL_5 (cid, sname, score) values ('002', '小刚', 62);
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 二. 窗口的确定
|
||||
|
||||
例子:
|
||||
|
||||
```sql
|
||||
select *, sum(score) over (partition by cid order by score rows between unbounded preceding and unbounded following) as '班级总分' from SQL_5;
|
||||
```
|
||||
|
||||
#### 分组子句(partition by)
|
||||
|
||||
不分组可以写成partition by null或者直接不写
|
||||
|
||||
后面可以跟多个列, 如 partition by cid, sname
|
||||
|
||||
**注意 partition by与group by的区别**
|
||||
|
||||
1)前者不会压缩行数但是后者会
|
||||
|
||||
2)后者只能选取分组的列和聚合的列
|
||||
|
||||
也就是说group by 后生成的结果集与原表的行数和列数都不同
|
||||
|
||||
#### 排序子句(order by)
|
||||
|
||||
不排序可以写成order by null 或者直接不写
|
||||
|
||||
asc或不写表示升序,desc表示降序
|
||||
|
||||
后面可以跟多个列, 如 order by cid, sname
|
||||
|
||||
#### 窗口子句(rows)
|
||||
|
||||
窗口子句的描述
|
||||
|
||||
1) 起始行: N preceding/unbounded preceding
|
||||
|
||||
2) 当前行: current row
|
||||
|
||||
3) 终止行: N following/unbounded following
|
||||
|
||||
举例:
|
||||
|
||||
rows between unbounded preceding and current row 从之前所有的行到当前行
|
||||
|
||||
rows between 2 preceding and current row 从前面两行到当前行
|
||||
|
||||
rows between current row and unbounded following 从当前行到之后所有的行
|
||||
|
||||
rows between current row and 1following 从当前行到后面一行
|
||||
|
||||
**注意:**
|
||||
|
||||
**排序子句后面缺少窗口子句,窗口规范默认是 rows between unbounded preceding and current row**
|
||||
|
||||
**排序子句和窗口子句都缺失,窗口规范默认是 rows between unbounded preceding and unbounded following**
|
||||
|
||||
#### 总体流程
|
||||
|
||||
1) 通过partition by 和 order by 子句确定大窗口( 定义出上界unbounded preceding和下界unbounded following)
|
||||
|
||||
2) 通过row 子句针对每一行数据确定小窗口(滑动窗口)
|
||||
|
||||
3) 对每行的小窗口内的数据执行函数并生成新的列
|
||||
|
||||
|
||||
|
||||
### 三. 函数分类
|
||||
|
||||
#### 排序类
|
||||
|
||||
rank, dense_rank, row_number
|
||||
|
||||
```sql
|
||||
-- 【排序类】
|
||||
-- 按班级分组后打上序号 不考虑并列
|
||||
select *, row_number() over (partition by cid order by score desc) as '不可并列排名' from SQL_5;
|
||||
-- 按班级分组后作跳跃排名 考虑并列
|
||||
select *, rank() over (partition by cid order by score desc) as '跳跃可并列排名' from SQL_5;
|
||||
-- 按班级分组后作连续排名 考虑并列
|
||||
select *, dense_rank() over (partition by cid order by score desc) as '连续可并列排名' from SQL_5;
|
||||
-- 合并起来对比
|
||||
select *, row_number() over (partition by cid order by score desc) as '不可并列排名' ,
|
||||
rank() over (partition by cid order by score desc) as '跳跃可并列排名',
|
||||
dense_rank() over (partition by cid order by score desc) as '连续可并列排名'
|
||||
from SQL_5;
|
||||
```
|
||||
|
||||
#### 聚合类
|
||||
|
||||
sum. avg, count, max, min
|
||||
|
||||
```sql
|
||||
-- 【聚合类】
|
||||
-- 让同一班级每个学生都知道班级总分是多少
|
||||
select *, sum(score) over (partition by cid) as '班级总分' from SQL_5;
|
||||
-- 或者可以写成
|
||||
select *, sum(score) over (partition by cid rows between unbounded preceding and unbounded following) as '班级总分' from SQL_5;
|
||||
|
||||
-- 计算同一班级,每个同学和比他分数低的同学的累计总分是多少
|
||||
select *, sum(score) over (partition by cid order by score) '累加分数' from SQL_5;
|
||||
-- 或者可以写成 其中rows between ... and 是规定窗口大小
|
||||
select *, sum(score) over (partition by cid order by score rows between unbounded preceding and current row) as '累加分数' from SQL_5;
|
||||
```
|
||||
|
||||
#### 跨行类
|
||||
|
||||
lag, lead
|
||||
|
||||
```sql
|
||||
-- 【跨行类】
|
||||
-- lag/lead 函数 参数1:比较的列 参数2: 偏移量 参数3:找不到的默认值
|
||||
-- 同一班级内,成绩比自己低一名的分数是多少
|
||||
select *, lag(score, 1) over (partition by cid order by score) as '低一名的分数' from SQL_5;
|
||||
-- 或者写成
|
||||
select *, lag(score, 1, 0) over (partition by cid order by score) as '低一名的分数' from SQL_5;
|
||||
|
||||
-- 同一班级内,成绩比自己高2名的分数是多少
|
||||
select *, lead(score, 2) over (partition by cid order by score) as '高两名的分数' from SQL_5;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 四. 相关题目
|
||||
|
||||
#### 表格
|
||||
|
||||
| cid | sname | course | score |
|
||||
| ---- | ----- | ------ | ----- |
|
||||
| 001 | 张三 | 语文 | 78 |
|
||||
| 002 | 小刚 | 语文 | 71 |
|
||||
| 001 | 李四 | 数学 | 56 |
|
||||
| 002 | 小明 | 数学 | 54 |
|
||||
| ... | ... | ... | ... |
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_6 (
|
||||
cid varchar(4),
|
||||
sname varchar(4),
|
||||
course varchar(10),
|
||||
score int
|
||||
);
|
||||
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '张三', '语文', 78);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小刚', '语文', 71);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '李四', '数学', 56);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '王五', '数学', 97);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小明', '数学', 54);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小刚', '数学', 67);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小红', '数学', 82);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '王五', '语文', 80);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '张三', '数学', 77);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小明', '语文', 58);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小红', '语文', 87);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '李四', '语文', 60);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '张三', '英语', 66);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小刚', '英语', 50);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '李四', '地理', 59);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '王五', '地理', 88);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小明', '地理', 45);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小刚', '地理', 66);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小红', '地理', 82);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '王五', '英语', 81);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '张三', '地理', 77);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小明', '英语', 55);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('002', '小红', '英语', 87);
|
||||
insert into SQL_6 (cid, sname, course, score) values ('001', '李四', '英语', 61);
|
||||
```
|
||||
|
||||
##### 分组内topN
|
||||
|
||||
问题1:求出每个学生成绩最高的三条记录
|
||||
|
||||
```sql
|
||||
select * from
|
||||
(
|
||||
select *, row_number() over (partition by sname order by score desc) as rn from SQL_6
|
||||
) temp
|
||||
where rn <= 3
|
||||
```
|
||||
|
||||
###### 公式:
|
||||
|
||||
```sql
|
||||
select * from
|
||||
(
|
||||
select *, row_number() over (partition by 分组列 order by 比较列) as rn from table
|
||||
) as tmp
|
||||
where rn <= N;
|
||||
```
|
||||
|
||||
|
||||
|
||||
##### 汇总分析
|
||||
|
||||
问题2:找出每门课程都高于班级课程平均分的学生
|
||||
|
||||
可以拆解成以下几个问题:
|
||||
|
||||
1)求出每个班级,每门课程的平均分
|
||||
|
||||
```sql
|
||||
with
|
||||
-- 1) 求出每个班级,每门课程的平均分
|
||||
t1 as
|
||||
(
|
||||
select *,
|
||||
avg(score) over (partition by cid, course) as 'avg'
|
||||
from SQL_6
|
||||
),
|
||||
```
|
||||
|
||||
2)将学生每门课程的成绩与所在班级的对应课程平均分相减,结果大于0就说明该学生的这门成绩高于课程平均分
|
||||
|
||||
```sql
|
||||
t2 as (
|
||||
select *,
|
||||
score - avg as 'del'
|
||||
from t1
|
||||
)
|
||||
```
|
||||
|
||||
3)“找出每门课程都高于班级课程平均分的学生”说明对于学生来说,最小的“相减结果”都是大于0的
|
||||
|
||||
```sql
|
||||
select sname from t2
|
||||
group by sname
|
||||
having min(del) > 0;
|
||||
```
|
||||
|
||||
合并后的SQL语句
|
||||
|
||||
```sql
|
||||
with
|
||||
t1 as
|
||||
(
|
||||
select *,
|
||||
avg(score) over (partition by cid, course) as 'avg'
|
||||
from SQL_6
|
||||
),
|
||||
t2 as (
|
||||
select *,
|
||||
score - avg as 'del'
|
||||
from t1
|
||||
)
|
||||
select sname from t2
|
||||
group by sname
|
||||
having min(del) > 0;
|
||||
|
||||
-- 或者
|
||||
select sname from (
|
||||
select *,
|
||||
score - avg as 'del'
|
||||
from (
|
||||
select *,
|
||||
avg(score) over (partition by cid, course) as 'avg'
|
||||
from SQL_6
|
||||
) t1
|
||||
) t2
|
||||
group by sname
|
||||
having min(del) > 0;
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 表格
|
||||
|
||||
| empno | ename | hire_date | salary | dept_no |
|
||||
| ----- | ----- | ---------- | ------ | ------- |
|
||||
| 001 | Adam | 2018-03-01 | 1000 | A |
|
||||
| 002 | Bill | 2021-03-01 | 1200 | A |
|
||||
| 003 | Cindy | 2016-03-01 | 1500 | A |
|
||||
| 004 | Danny | 2020-03-01 | 5000 | A |
|
||||
| 005 | Eason | 2020-03-01 | 4000 | B |
|
||||
| 006 | Fred | 2018-03-01 | 3500 | B |
|
||||
| 007 | Gary | 2017-03-01 | 1800 | B |
|
||||
| 008 | Hugo | 2020-03-01 | 2500 | B |
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_7 (
|
||||
empno varchar(4),
|
||||
ename varchar(10),
|
||||
hire_date varchar(10),
|
||||
salary int,
|
||||
dept_no varchar(2)
|
||||
);
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('001', 'Adam', '2018-03-01', 1000, 'A');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('002', 'Bill', '2021-03-01', 1200, 'A');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('003', 'Cindy', '2016-03-01', 1500, 'A');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('004', 'Danny', '2020-03-01', 5000, 'A');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('005', 'Eason', '2020-03-01', 4000, 'B');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('006', 'Fred', '2018-03-01', 3500, 'B');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('007', 'Gary', '2017-03-01', 1800, 'B');
|
||||
insert into SQL_7 (empno, ename, hire_date, salary, dept_no) values ('008', 'Hugo', '2020-03-01', 4500, 'B');
|
||||
|
||||
select * from SQL_7;
|
||||
```
|
||||
|
||||
##### 分组内topN
|
||||
|
||||
问题一:求出每个部门工资最高的前三名员工
|
||||
|
||||
```sql
|
||||
select * from
|
||||
(
|
||||
select *, row_number() over (partition by dept_no order by salary desc) as rn from SQL_7
|
||||
) as tmp
|
||||
where rn <= 3;
|
||||
```
|
||||
|
||||
|
||||
|
||||
##### 汇总分析
|
||||
|
||||
问题二:计算这些员工的工资占所属部门总工资的百分比
|
||||
|
||||
```sql
|
||||
with
|
||||
t1 as (
|
||||
select * , sum(salary) over (partition by dept_no) as 'sum_sal' from SQL_7
|
||||
),
|
||||
t2 as (
|
||||
select *, round(salary*100/sum_sal,2) as 'percentage' from t1
|
||||
)
|
||||
select * from t2;
|
||||
```
|
||||
|
||||
问题三:对各部门员工的工资进行从小到大排序,排名前30%为低层,30%-80%为中层,高于80%为高层,并打上标签
|
||||
|
||||
```label
|
||||
with
|
||||
t1 as (
|
||||
select * , row_number() over (partition by dept_no order by salary) as cnt,
|
||||
count(empno) over (partition by dept_no) as 'sum' from SQL_7
|
||||
),
|
||||
t2 as (
|
||||
select *, round(cnt/sum,2) as 'percentage' from t1
|
||||
),
|
||||
t3 as (
|
||||
select *, case when percentage <= 0.3 then '低层'
|
||||
when percentage <= 0.8 then '中层'
|
||||
when percentage <= 1 then '高层' end as 'label'
|
||||
from t2
|
||||
)
|
||||
select empno, ename, hire_date, salary, dept_no, label from t3;
|
||||
```
|
||||
|
||||
问题四:统计每年入职总数以及截至本年累计入职总人数(本年总入职人数 + 本年之前所有年的总入职人数之和)
|
||||
|
||||
```sql
|
||||
select year(hire_date) as hire_year, count(empno) as cnt
|
||||
from SQL_7
|
||||
group by year(hire_date) order by hire_year;
|
||||
```
|
||||
|
||||
```sql
|
||||
with t1 as (
|
||||
select year(hire_date) as hire_year, count(empno) as cnt from SQL_7 group by year(hire_date) order by hire_year
|
||||
)
|
||||
|
||||
select *, sum(cnt) over(partition by null rows between unbounded preceding and current row) as sum from t1;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 五. 技巧
|
||||
|
||||
1)分组内topN公式
|
||||
|
||||
```sql
|
||||
select * from
|
||||
(
|
||||
select *, row_number() over (partition by 分组列 order by 比较列) as rn from table
|
||||
) as tmp
|
||||
where rn <= N;
|
||||
```
|
||||
|
||||
2) 窗口函数 -> 生成辅助列(相当于高级语言的临时变量)
|
||||
|
||||
3) with 语句 -> 生成临时表(相当于高级语言的局部方法)
|
||||
|
||||
把复杂的问题拆分成多个子问题并用临时表去表达
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
324
SQL-行转列与列转行.md
Normal file
324
SQL-行转列与列转行.md
Normal file
@ -0,0 +1,324 @@
|
||||
# SQL 讲解 —— 行转列 与 列转行
|
||||
|
||||
## 行转列
|
||||
|
||||
### 题目1
|
||||
|
||||
#### 描述
|
||||
|
||||
```
|
||||
name subject score
|
||||
张三 语文 78
|
||||
张三 数学 88
|
||||
张三 英语 98
|
||||
李四 语文 89
|
||||
李四 数学 76
|
||||
李四 英语 90
|
||||
王五 语文 99
|
||||
王五 数学 66
|
||||
王五 英语 91
|
||||
|
||||
name 语文 数学 英语
|
||||
张三 78 88 98
|
||||
李四 89 76 90
|
||||
王五 99 66 91
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
create table SQL_1
|
||||
(
|
||||
name varchar(20),
|
||||
subject varchar(20),
|
||||
score float
|
||||
);
|
||||
insert into SQL_1 (name, subject, score) values ('张三', '语文', 78);
|
||||
insert into SQL_1 (name, subject, score) values ('张三', '数学', 88);
|
||||
insert into SQL_1 (name, subject, score) values ('张三', '英语', 98);
|
||||
insert into SQL_1 (name, subject, score) values ('李四', '语文', 89);
|
||||
insert into SQL_1 (name, subject, score) values ('李四', '数学', 76);
|
||||
insert into SQL_1 (name, subject, score) values ('李四', '英语', 90);
|
||||
insert into SQL_1 (name, subject, score) values ('王五', '语文', 99);
|
||||
insert into SQL_1 (name, subject, score) values ('王五', '数学', 66);
|
||||
insert into SQL_1 (name, subject, score) values ('王五', '英语', 91);
|
||||
select * from SQL_1;
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 解题步骤
|
||||
|
||||
1) 确定分组列,转换列,数据列
|
||||
|
||||
2) 生成伪列
|
||||
|
||||
3) 做分组查询
|
||||
|
||||
4) 选择合适的聚合函数
|
||||
|
||||
|
||||
|
||||
#### 两步法
|
||||
|
||||
##### 公式:
|
||||
|
||||
```sql
|
||||
select 分组列,
|
||||
聚合函数(m1) as 列名1,
|
||||
聚合函数(m2) as 列名2,
|
||||
聚合函数(m3) as 列名3
|
||||
from (select *,
|
||||
case 转换列 when 转换列值1 then 数据列 else ... end as m1,
|
||||
case 转换列 when 转换列值2 then 数据列 else ... end as m2,
|
||||
case 转换列 when 转换列值3 then 数据列 else ... end as m3
|
||||
from 表名) 临时表名
|
||||
group by 分组列;
|
||||
```
|
||||
|
||||
##### 解题SQL
|
||||
|
||||
```sql
|
||||
select name,
|
||||
sum(m1) as 语文,
|
||||
sum(m2) as 数学,
|
||||
sum(m3) as 英语
|
||||
from (select *,
|
||||
case subject when '语文' then score else 0 end as m1,
|
||||
case subject when '数学' then score else 0 end as m2,
|
||||
case subject when '英语' then score else 0 end as m3
|
||||
from sql_1) tmp
|
||||
group by name;
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 一步法
|
||||
|
||||
##### 公式:
|
||||
|
||||
```sql
|
||||
select 分组列,
|
||||
聚合函数(case 转换列 when 转换列值1 then 数据列 else ... end) as 列名1,
|
||||
聚合函数(case 转换列 when 转换列值2 then 数据列 else ... end) as 列名2,
|
||||
聚合函数(case 转换列 when 转换列值3 then 数据列 else ... end) as 列名3
|
||||
...
|
||||
from 表名
|
||||
group by 分组列;
|
||||
|
||||
select 分组列,
|
||||
聚合函数(case when 转换列=转换列值1 then 数据列 else ... end) as 列名1,
|
||||
聚合函数(case when 转换列=转换列值2 then 数据列 else ... end) as 列名2,
|
||||
聚合函数(case when 转换列=转换列值3 then 数据列 else ... end) as 列名3
|
||||
...
|
||||
from 表名
|
||||
group by 分组列;
|
||||
```
|
||||
|
||||
##### 解题SQL
|
||||
|
||||
```sql
|
||||
select name,
|
||||
sum(case subject when '语文' then score else 0 end) as 语文,
|
||||
sum(case subject when '数学' then score else 0 end) as 数学,
|
||||
sum(case subject when '英语' then score else 0 end) as 英语
|
||||
from sql_1
|
||||
group by name;
|
||||
|
||||
select name,
|
||||
sum(case when subject = '语文' then score else 0 end) as 语文,
|
||||
sum(case when subject = '数学' then score else 0 end) as 数学,
|
||||
sum(case when subject = '英语' then score else 0 end) as 英语
|
||||
from sql_1
|
||||
group by name;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 题目2
|
||||
|
||||
#### 描述
|
||||
|
||||
```txt
|
||||
# 日期 结果
|
||||
# 2022-01-01 胜
|
||||
# 2022-01-01 胜
|
||||
# 2022-01-02 负
|
||||
# 2022-01-02 负
|
||||
# 2022-01-01 负
|
||||
# 2022-01-02 负
|
||||
# 2022-01-02 胜
|
||||
|
||||
# 日期 胜 负
|
||||
# 2022-01-01 2 1
|
||||
# 2022-01-02 1 3
|
||||
```
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
create table SQL_2(
|
||||
ddate varchar(10), result varchar(2)
|
||||
);
|
||||
|
||||
insert into SQL_2 (ddate, result) values('2022-01-01','胜');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-01','胜');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-02','负');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-02','负');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-01','负');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-02','负');
|
||||
insert into SQL_2 (ddate, result) values('2022-01-02','胜');
|
||||
select * from SQL_2;
|
||||
```
|
||||
|
||||
#### 解题SQL
|
||||
|
||||
```sql
|
||||
select ddate,
|
||||
sum(case when result = '胜' then 1 else 0 end) as 胜,
|
||||
sum(case when result = '负' then 1 else 0 end) as 负
|
||||
from sql_2
|
||||
group by ddate;
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 列转行
|
||||
|
||||
### 题目3
|
||||
|
||||
#### 描述
|
||||
|
||||
```txt
|
||||
name 语文 数学 英语
|
||||
张三 78 88 98
|
||||
李四 89 76 90
|
||||
王五 99 66 91
|
||||
|
||||
name subject score
|
||||
张三 语文 78
|
||||
张三 数学 88
|
||||
张三 英语 98
|
||||
李四 语文 89
|
||||
李四 数学 76
|
||||
李四 英语 90
|
||||
王五 语文 99
|
||||
王五 数学 66
|
||||
王五 英语 91
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_3 (
|
||||
name varchar(20),
|
||||
语文 float,
|
||||
数学 float,
|
||||
英语 float
|
||||
);
|
||||
|
||||
insert into SQL_3 (name, '语文', '数学', '英语') values ('张三', 78, 88, 98);
|
||||
insert into SQL_3 (name, '语文', '数学', '英语') values ('李四', 89, 76, 90);
|
||||
insert into SQL_3 (name, '语文', '数学', '英语') values ('王五', 99, 66, 91);
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 解题步骤
|
||||
|
||||
1) 确定转换列,非转换列
|
||||
|
||||
2) 生成新列
|
||||
|
||||
3) 使用union或union all 进行合并
|
||||
|
||||
4) 根据需要进行order by
|
||||
|
||||
|
||||
|
||||
#### 公式
|
||||
|
||||
```sql
|
||||
SELECT 非转换列, '转换列1' AS 新转换列名, 转换列1 AS 新数据列名 FROM 表名
|
||||
UNION ALL
|
||||
SELECT 非转换列, '转换列2' AS 新转换列名, 转换列2 AS 新数据列名 FROM 表名
|
||||
UNION ALL
|
||||
SELECT 非转换列, '转换列3' AS 新转换列名, 转换列3 AS 新数据列名 FROM 表名
|
||||
ORDER BY ...;
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 解题SQL
|
||||
|
||||
```sql
|
||||
SELECT name,'语文' AS subject,语文 AS score FROM SQL_3
|
||||
UNION ALL
|
||||
SELECT name,'数学' AS subject,数学 AS score FROM SQL_3
|
||||
UNION ALL
|
||||
SELECT name,'英语' AS subject,英语 AS score FROM SQL_3
|
||||
ORDER BY name ASC, subject DESC;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 题目4
|
||||
|
||||
#### 描述
|
||||
|
||||
```txt
|
||||
Q1 Q2 Q3 Q4
|
||||
1000 2000 3000 4000
|
||||
|
||||
季度 业绩
|
||||
Q1 1000
|
||||
Q2 2000
|
||||
Q3 3000
|
||||
Q4 4000
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_4 (
|
||||
Q1 int, Q2 int, Q3 int, Q4 int
|
||||
);
|
||||
|
||||
insert into SQL_4 values (1000, 2000, 3000, 4000);
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 解题SQL
|
||||
|
||||
```sql
|
||||
SELECT 'Q1' AS 季度, Q1 AS 业绩 FROM SQL_4
|
||||
UNION ALL
|
||||
SELECT 'Q2' AS 季度, Q2 AS 业绩 FROM SQL_4
|
||||
UNION ALL
|
||||
SELECT 'Q3' AS 季度, Q3 AS 业绩 FROM SQL_4
|
||||
UNION ALL
|
||||
SELECT 'Q4' AS 季度, Q4 AS 业绩 FROM SQL_4
|
||||
ORDER BY 季度;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 技巧:
|
||||
|
||||
扩展列:select ... as 新列名
|
||||
|
||||
减少列:直接不写
|
||||
|
||||
扩展行:union/ union all
|
||||
|
||||
减少行: 聚合函数
|
||||
|
||||
|
||||
|
231
SQL窗口函数(二).md
Normal file
231
SQL窗口函数(二).md
Normal file
@ -0,0 +1,231 @@
|
||||
# SQL窗口函数(二)—— 连续问题
|
||||
|
||||
### 题目一
|
||||
|
||||
#### 表格
|
||||
|
||||
| user_id | login_date |
|
||||
| ------- | ---------- |
|
||||
| A | 2022-09-02 |
|
||||
| A | 2022-09-03 |
|
||||
| A | 2022-09-04 |
|
||||
| B | 2021-11-25 |
|
||||
| B | 2021-12-31 |
|
||||
| C | 2022-01-01 |
|
||||
| C | 2022-04-04 |
|
||||
| C | 2022-09-03 |
|
||||
| C | 2022-09-04 |
|
||||
| C | 2022-09-05 |
|
||||
| A | 2022-09-03 |
|
||||
| D | 2022-10-20 |
|
||||
| D | 2022-10-21 |
|
||||
| A | 2022-10-03 |
|
||||
| D | 2022-10-22 |
|
||||
| D | 2022-10-23 |
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_8
|
||||
(
|
||||
user_id varchar(2),
|
||||
login_date date
|
||||
);
|
||||
INSERT INTO SQL_8 (user_id,login_date)
|
||||
VALUES ('A', '2022-09-02'), ('A', '2022-09-03'), ('A', '2022-09-04'), ('B', '2021-11-25'),
|
||||
('B', '2021-12-31'), ('C', '2022-01-01'), ('C', '2022-04-04'), ('C', '2022-09-03'),
|
||||
('C', '2022-09-05'), ('C', '2022-09-04'), ('A', '2022-09-03'), ('D', '2022-10-20'),
|
||||
('D', '2022-10-21'), ('A', '2022-10-03'), ('D', '2022-10-22'), ('D', '2022-10-23');
|
||||
```
|
||||
|
||||
#### 问题
|
||||
|
||||
找出这张表中所有的连续3天登录用户
|
||||
|
||||
#### 分析
|
||||
|
||||
连续N天登录用户,要求数据行满足以下条件:
|
||||
|
||||
1) userid 要相同,表示同一用户
|
||||
|
||||
2) 同一用户每行记录以登录时间从小到大排序
|
||||
|
||||
3) 后一行记录比前一行记录的登录时间多一天
|
||||
|
||||
4) 数据行数大于等于N
|
||||
|
||||
#### 解答
|
||||
|
||||
```sql
|
||||
-- 方法一
|
||||
with t1 as (
|
||||
select distinct user_id, login_date from SQL_8
|
||||
),
|
||||
t2 as (
|
||||
select *, row_number() over (partition by user_id order by login_date) as rn from t1
|
||||
),
|
||||
t3 as (
|
||||
select *, DATE_SUB(login_date, interval rn day) as sub from t2
|
||||
)
|
||||
select distinct user_id from t3 group by user_id, sub having count(user_id) >= 3;
|
||||
|
||||
-- 方法二
|
||||
with t1 as (
|
||||
select distinct user_id, login_date from SQL_8
|
||||
),
|
||||
t2 as (
|
||||
select *, DATEDIFF(login_date, lag(login_date, 1) over (partition by user_id order by login_date)) as diff from t1
|
||||
)
|
||||
select user_id from t2 where diff = 1 group by user_id having count(user_id) >= 2;
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 题目二
|
||||
|
||||
#### 表格
|
||||
|
||||
| player_id | score | score_time |
|
||||
| --------- | ----- | ------------------- |
|
||||
| B3 | 1 | 2022-09-20 19:00:14 |
|
||||
| A2 | 1 | 2022-09-20 19:01:04 |
|
||||
| A2 | 3 | 2022-09-20 19:01:16 |
|
||||
| A2 | 3 | 2022-09-20 19:02:05 |
|
||||
| A2 | 2 | 2022-09-20 19:02:25 |
|
||||
| B5 | 2 | 2022-09-20 19:02:54 |
|
||||
| A4 | 3 | 2022-09-20 19:03:10 |
|
||||
| B1 | 2 | 2022-09-20 19:03:34 |
|
||||
| B1 | 2 | 2022-09-20 19:03:58 |
|
||||
| B1 | 3 | 2022-09-20 19:04:07 |
|
||||
| A2 | 1 | 2022-09-20 19:04:19 |
|
||||
| A3 | 2 | 2022-09-20 19:04:31 |
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_9
|
||||
(
|
||||
player_id varchar(2),
|
||||
score int,
|
||||
score_time datetime
|
||||
);
|
||||
INSERT INTO SQL_9 (player_id, score, score_time)
|
||||
VALUES ('B3', 1, '2022-09-20 19:00:14'), ('A2', 1, '2022-09-20 19:01:04'),
|
||||
('A2', 3, '2022-09-20 19:01:16'), ('A2', 3, '2022-09-20 19:02:05'),
|
||||
('A2', 2, '2022-09-20 19:02:25'), ('B3', 2, '2022-09-20 19:02:54'),
|
||||
('A4', 3, '2022-09-20 19:03:10'), ('B1', 2, '2022-09-20 19:03:34'),
|
||||
('B1', 2, '2022-09-20 19:03:58'), ('B1', 3, '2022-09-20 19:04:07'),
|
||||
('A2', 1, '2022-09-20 19:04:19'), ('B3', 2, '2022-09-20 19:04:31');
|
||||
```
|
||||
|
||||
#### 问题
|
||||
|
||||
统计出连续三次(及以上)为球队得分的球员名单
|
||||
|
||||
#### 分析
|
||||
|
||||
连续N次以上为球队得分, 要求数据行满足以下条件:
|
||||
|
||||
1) player_id 要相同表示同一球员
|
||||
|
||||
2) 每行记录以得分时间从小到大排序
|
||||
|
||||
3) 数据行数大于等于N
|
||||
|
||||
#### 解答
|
||||
|
||||
```sql
|
||||
-- 方法一
|
||||
with t1 as (
|
||||
select *, lag(player_id, 1) over (order by score_time) as last_play_id from SQL_9
|
||||
)
|
||||
select distinct player_id from t1 where player_id = last_play_id group by player_id having count(player_id) >= 2;
|
||||
|
||||
-- 方法二
|
||||
with t1 as (
|
||||
select *, row_number() over (order by score_time) as rn from SQL_9
|
||||
),
|
||||
t2 as (
|
||||
select *, row_number() over (order by score_time) + 1 as rn from SQL_9
|
||||
),
|
||||
t3 as (
|
||||
select t1.player_id as player_id from t1 join t2 on t1.rn = t2.rn and t1.player_id = t2.player_id
|
||||
)
|
||||
select distinct player_id from t3 group by player_id having count(player_id) >= 2;
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 题目三
|
||||
|
||||
#### 表格
|
||||
|
||||
| log_id |
|
||||
| :----: |
|
||||
| 1 |
|
||||
| 2 |
|
||||
| 3 |
|
||||
| 7 |
|
||||
| 8 |
|
||||
| 10 |
|
||||
|
||||
#### 脚本
|
||||
|
||||
```sql
|
||||
CREATE TABLE SQL_10
|
||||
(
|
||||
log_id int
|
||||
);
|
||||
INSERT INTO SQL_10 (log_id) VALUES (1), (2), (3), (7), (8), (10);
|
||||
```
|
||||
|
||||
#### 问题
|
||||
|
||||
编写SQL 查询得到 Logs 表中的连续区间的开始数字和结束数字。按照 start_id 排序。查询结果格式如下:
|
||||
|
||||
| start_id | end_id |
|
||||
| -------- | ------ |
|
||||
| 1 | 3 |
|
||||
| 7 | 8 |
|
||||
| 10 | 10 |
|
||||
|
||||
#### 解答
|
||||
|
||||
```sql
|
||||
-- 方法一
|
||||
with t1 as (
|
||||
select *, log_id - row_number() over (order by log_id) as gr from SQL_10
|
||||
)
|
||||
|
||||
select min(log_id) as start_id, max(log_id) as end_id from t1 group by gr
|
||||
|
||||
-- 方法二
|
||||
with t1 as (
|
||||
select *, log_id - row_number() over (order by log_id) as gr, log_id - lag(log_id,1) over () as diff from SQL_10
|
||||
),
|
||||
t2 as (
|
||||
select log_id, gr from t1 where ifnull(diff,-1) <> 1
|
||||
),
|
||||
t3 as (
|
||||
select *, log_id - row_number() over (order by log_id) as gr, log_id - lead(log_id,1) over () as diff from SQL_10
|
||||
),
|
||||
t4 as (
|
||||
select log_id, gr from t3 where ifnull(diff, 1) <> -1
|
||||
)
|
||||
select t2.log_id as start_id, t4.log_id as end_id from t2, t4 where t2.gr = t4.gr;
|
||||
```
|
||||
|
||||
### 技巧
|
||||
|
||||
如何求连续区间?
|
||||
|
||||
1)行号过滤法
|
||||
|
||||
通过row_number() 生成连续行号,与区间列进行差值运算,得到的临时结果如果相同表示为同一连续区间
|
||||
|
||||
2) 错位比较法
|
||||
|
||||
通过row_number() / row_number() + 1 分别生成原生的和错位的连续行号列,进行连表操作
|
||||
|
||||
也可以通过lag/lead函数直接生成错位列
|
@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
# Centos 安装 Docker
|
||||
# Linux 安装 Docker
|
||||
|
||||
|
||||
|
||||
@ -18,6 +18,39 @@
|
||||
|
||||
|
||||
|
||||
## oracle linxu
|
||||
|
||||
1. 执行以下命令,以安装Docker依赖项:
|
||||
|
||||
```
|
||||
sudo yum -y install yum-utils device-mapper-persistent-data lvm2
|
||||
```
|
||||
|
||||
2. 执行以下命令,以添加Docker官方GPG key:
|
||||
|
||||
```
|
||||
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
||||
```
|
||||
|
||||
3. 执行以下命令,以安装Docker CE:
|
||||
|
||||
```
|
||||
sudo yum install docker-ce
|
||||
```
|
||||
|
||||
4. 启动并设置Docker服务为开机自启:
|
||||
|
||||
```
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
通过`docker --version`命令,您可以检查Docker是否已经安装。如果命令输出了版本信息,说明已经成功安装Docker CE。
|
||||
|
||||
希望这次能给您提供一个更简洁的方法。
|
||||
|
||||
|
||||
|
||||
## 启动服务
|
||||
|
||||
```bash
|
||||
@ -66,12 +99,15 @@ Docker中国:https://registry.docker-cn.com
|
||||
```
|
||||
sudo mkdir -p /etc/docker
|
||||
|
||||
#注意EOF前不能有空格
|
||||
sudo tee /etc/docker/daemon.json <<-'EOF'
|
||||
{
|
||||
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
```
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl restart docker
|
||||
```
|
||||
|
@ -22,7 +22,6 @@ s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可
|
||||
可以使用正则 特殊字符\转义
|
||||
|
||||
|
||||
sed ”s/要被取代的字串/新的字串/g“ fileName
|
||||
sed "s/要被取代的字串/新的字串/g" fileName
|
||||
```
|
||||
|
||||
|
||||
|
@ -637,7 +637,15 @@ psql -Uicctestedb -dicctestedb -h192.168.53.123 -f ~/
|
||||
# -O 不设置表归属,
|
||||
# -F c 自定义压缩
|
||||
# -v 显示详情
|
||||
./pg_dump -Uenterprisedb -diccedb -h192.168.53.118 -O -v -F c -f ~/diccedb_202207_29.data.sql
|
||||
./pg_dump -Uenterprisedb -diccedb -h192.168.53.118 -O -v -F c -f ~/alg.da
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 数据导入
|
||||
|
||||
```shell
|
||||
|
||||
#导入数据
|
||||
#-c 指定恢复过程中清空目标数据库中的现有表
|
||||
@ -655,10 +663,6 @@ psql -Uicctestedb -dicctestedb -h192.168.53.123 -f ~/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### COPY 导出导出部分数据
|
||||
|
||||
```sh
|
||||
|
214
redis/redis-3.0.3,哨兵集群.md
Normal file
214
redis/redis-3.0.3,哨兵集群.md
Normal file
@ -0,0 +1,214 @@
|
||||
## redis-v3.0.3哨兵集群搭建文档
|
||||
|
||||
|
||||
|
||||
### 准备工作
|
||||
|
||||
### 主机
|
||||
|
||||
准备三台全新 centos linux 服务器
|
||||
|
||||
固定IP
|
||||
|
||||
```
|
||||
192.168.1.11
|
||||
192.168.1.12
|
||||
192.168.1.13
|
||||
```
|
||||
|
||||
**以下命令如无特殊说明 在三台主机中均要执行**
|
||||
|
||||
准备环境
|
||||
|
||||
```bash
|
||||
yum install make gcc wget
|
||||
```
|
||||
|
||||
创建用户
|
||||
|
||||
```bash
|
||||
useradd redis
|
||||
```
|
||||
|
||||
创建相关目录
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/{app/redis,applog}
|
||||
```
|
||||
|
||||
授权
|
||||
|
||||
```bash
|
||||
chown -R redis:redis /opt/app/redis/
|
||||
```
|
||||
|
||||
```bash
|
||||
chown -R redis:redis /opt/applog/redis/
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 编译源码
|
||||
|
||||
切换用户
|
||||
|
||||
```bash
|
||||
su - redis
|
||||
```
|
||||
|
||||
下载源码
|
||||
|
||||
```bash
|
||||
cd /opt/app/redis/
|
||||
wget https://download.redis.io/releases/redis-3.0.3.tar.gz
|
||||
```
|
||||
|
||||
|
||||
|
||||
解压源码
|
||||
|
||||
```bash
|
||||
tar -zxvf redis-3.0.3.tar.gz
|
||||
```
|
||||
|
||||
|
||||
|
||||
编译源码 这里为了和生产一致 使用libc 内存分配器
|
||||
|
||||
```bash
|
||||
cd redis-3.0.3
|
||||
make MALLOC=libc
|
||||
```
|
||||
|
||||
安装
|
||||
|
||||
```bash
|
||||
make PREFIX=/opt/app/redis/ install
|
||||
```
|
||||
|
||||
|
||||
|
||||
配置 path
|
||||
|
||||
```bash
|
||||
echo 'export PATH=$PATH:/opt/app/redis/bin' >> ~/.bashrc
|
||||
|
||||
source ~/.bashrc
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 配置redis
|
||||
|
||||
复制配置文件
|
||||
|
||||
```bash
|
||||
cp /opt/app/redis/redis-3.0.3/src/redis.conf /opt/app/redis/
|
||||
|
||||
cp /opt/app/redis/redis-3.0.3/src/sentinel.conf /opt/app/redis/
|
||||
```
|
||||
|
||||
编辑配置文件 redis.conf
|
||||
|
||||
```bash
|
||||
sed -i 's/daemonize no/daemonize yes/g' redis.conf
|
||||
|
||||
sed -i 's|^logfile ""$|logfile "/opt/applog/redis/redis.log"|g' redis.conf
|
||||
|
||||
sed -i 's|^dir "./"$|dir "/opt/app/redis/"|g' redis.conf
|
||||
|
||||
sed -i 's/appendonly no/appendonly yes/g' redis.conf
|
||||
|
||||
sed -i 's/^# cluster-node-timeout 15000$/cluster-node-timeout 5000/g' redis.conf
|
||||
#设置主从复制密码
|
||||
sed -i 's/^# masterauth <master-password>$/masterauth dUw~7a)6/g' redis.conf
|
||||
#设置 节点密码
|
||||
sed -i 's/^# requirepass foobared$/requirepass dUw~7a)6/g' redis.conf
|
||||
```
|
||||
|
||||
|
||||
|
||||
配置主从节点
|
||||
|
||||
在 192.168.1.12,192.168.1.13 两台机子中执行
|
||||
|
||||
```bash
|
||||
echo "slaveof 10.23.101.3 6379" >> redis.conf
|
||||
```
|
||||
|
||||
|
||||
|
||||
编辑配置文件 sentinel.conf
|
||||
|
||||
```bash
|
||||
sed -i 's|^\(sentinel monitor mymaster\) 127.0.0.1|\1 181.168.1.11|' sentinel.conf
|
||||
|
||||
#设置哨兵密码
|
||||
sed -i 's/^#sentinel auth-pass <master-name> <password>/sentinel auth-pass mymaster HmpYZ2KB/g' sentinel.conf
|
||||
|
||||
echo "daemonize yes" >> sentinel.conf
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
编写动脚本
|
||||
|
||||
```bash
|
||||
echo "bin/redis-server redis.config">/opt/app/redis/start.sh
|
||||
chmod 775 start.sh
|
||||
|
||||
echo "bin/redis-sentinel sentinel.config">/opt/app/redis/start-sentinel.sh
|
||||
chmod 775 start.sh
|
||||
```
|
||||
|
||||
指定用户启动
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
su -s /bin/bash -c "$(pwd)/bin/redis-sentinel $(pwd)/sentinel.conf " redis
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 启动
|
||||
|
||||
先启动三个redis节点
|
||||
|
||||
```bash
|
||||
bash start.sh
|
||||
```
|
||||
|
||||
再启动 sentinel j节点
|
||||
|
||||
```bash
|
||||
bash start-sentinel.sh
|
||||
```
|
||||
|
||||
|
||||
|
||||
### 验证
|
||||
|
||||
登录三个redis节点 分别写入key
|
||||
|
||||
192.168.1.11 成功写入 并同步至 192.168.1.12,192.168.1.13
|
||||
192.168.1.12 写入失败
|
||||
192.168.1.13 写入失败
|
||||
|
||||
|
||||
|
||||
登录哨兵节点 查看哨兵信息
|
||||
|
||||
```bash
|
||||
redis-cli -p 26379
|
||||
|
||||
sentinel sentinels mymaster
|
||||
```
|
||||
|
||||
|
||||
|
||||
杀死 主节点
|
||||
|
||||
分别查看 另外两台redis 的info 信息 是否发生切换
|
Loading…
x
Reference in New Issue
Block a user