Hexo 使用plantuml

hexo-filter-plantuml

1
npm install hexo-filter-plantuml --save 

这个插件支持,使用markdown代码块来绘图,语言选择plantuml即可:

```plantuml
@startuml
Bob->Alice : hello
@enduml
```

显示效果:

阅读全文 »

自己实现一个BigInterger

2^31-1

要求这个整数不会溢出
要求可以对该整数进行加减法

String类

为什么不可以继承String类?因为String是final修饰的
String类为什么不可以改变
因为String使用final修饰的char数组保存字符的。

StringBuffer类

StringBuffer默认长度是多少?
16个字节

StringBuffer如何扩容
原来的长度*2+2

native修饰符

有这个修饰符的方法,表示java调用的时候本地方法实现,
也就是调用C语言的代码实现

本地方法栈,就是C语言方法的专用的栈

使用vscode

安装Graphviz Markdown Preview插件

dot语法

有向图

1
2
3
4
5
digraph g {
a->b;
b->c;
c->a;
}

如下图所示:

1
2
3
4
5
digraph g {
a->b;
b->c;
c->a;
}

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#@startdot
digraph demo {
label="示例"
bgcolor="beige"
node[color="grey"]
father[label="爸爸", shape="box"]
mother[label="妈妈", shape="box"]
brother[label="哥哥", shape="circle"]
sister[label="姐姐", shape="circle"]
node[color="#FF6347"]
strangers[label="路人"]
edge[color="#FF6347"]
father->mother[label="夫妻", dir="both"]
father->brother[label="父子"]
father->sister[label="父子"]
father->我[label="父子"]
mother->{brother,sister,我}[label="母子"]
{rank=same; father, mother}
{rank=same; brother,sister,我}
}
#@enddot

显示效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#@startdot

digraph demo {
label="示例"
bgcolor="beige"

node[color="grey"]

father[label="爸爸", shape="box"]
mother[label="妈妈", shape="box"]
brother[label="哥哥", shape="circle"]
sister[label="姐姐", shape="circle"]
node[color="#FF6347"]
strangers[label="路人"]

edge[color="#FF6347"]

father->mother[label="夫妻", dir="both"]
father->brother[label="父子"]
father->sister[label="父子"]
father->我[label="父子"]

mother->{brother,sister,我}[label="母子"]

{rank=same; father, mother}
{rank=same; brother,sister,我}
}
#@enddot

shape示例

代码:

1
2
3
4
5
6
7
8
9
10
11
12
digraph demo {
bgcolor="floralwhite"
"box"[shape=box]
"polygon"[shape=polygon,sides=7]
"ellipse"[shape=ellipse]
"circle"[shape=circle]
"point"[shape=point]
"triangle"[shape=triangle]
"invtriangle"[shape=invtriangle]
"plaintext"[shape=plaintext]
"diamond"[shape=diamond]
}

显示效果:

1
2
3
4
5
6
7
8
9
10
11
12
digraph demo {
bgcolor="floralwhite"
"box"[shape=box]
"polygon"[shape=polygon,sides=7]
"ellipse"[shape=ellipse]
"circle"[shape=circle]
"point"[shape=point]
"triangle"[shape=triangle]
"invtriangle"[shape=invtriangle]
"plaintext"[shape=plaintext]
"diamond"[shape=diamond]
}

矩形

1
2
3
digraph {
hello [shape=record label="first|second|last"]
}
1
2
3
digraph {
hello [shape=record label="first|second|last"]
}

问题描述

VScode中写markdown时,可以安装插件,然后在代码块中接口渲染dot
但是在Hexo,没有很方便的插件

所以

使用svg在线渲染服务

1
2
3
4
5
6
7
8
9
10
11
12
13
![xxx](https://g.gravizo.com/svg?
digraph demo {
rankdir=LR;
node [shape=record];
h [shape=ellipse];
n [shape=ellipse];

a [label="{1|null}" color="red"];

h -> null;
n ->a;
}
)

图片

方法1:进行URL编码后使用

但是这样的写法在hexo不会渲染成功,需要进行URL编码:

1
![xxx](https://g.gravizo.com/svg?digraph%20demo%20%7Brankdir%3DLR%3Bnode%20%5Bshape%3Drecord%5D%3Bh%20%5Bshape%3Dellipse%5D%3Bn%20%5Bshape%3Dellipse%5D%3Ba%20%5Blabel%3D%22%7B1%7Cnull%7D%22%20color%3D%22red%22%5D%3Bh%20-%3E%20null%3Bn%20-%3Ea%3B%7D)

渲染效果如下:

xxx

方法2:写在一行

1
![xxx](https://g.gravizo.com/svg?digraph demo {rankdir=LR;node [shape=record];h [shape=ellipse];n [shape=ellipse];a [label="{1|null}" color="red"];h -> null;n ->a;})

渲染效果:

![xxx](https://g.gravizo.com/svg?digraph demo {rankdir=LR;node [shape=record];h [shape=ellipse];n [shape=ellipse];a [label=”{1|null}” color=”red”];h -> null;n ->a;})

参考资料

https://juejin.cn/post/6844903702109634568
http://g.gravizo.com/
http://www.plantuml.com/plantuml

头插法创建链表

思想:把新创建的节点插入到头节点的前面作为新的头节点。

代码

成员变量

1
2
private int data;
private Node next;

头插法代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* 使用头插入法创建链表。
* 所谓头插法,就是新创建的节点插入到旧的头结点的前面,作为新的头结点。
*
* @return 链表的头结点的引用(地址)
*/
public static Node createLinkByHead() {
Node h = null;
Node n = null;
Scanner scanner = new Scanner(System.in);
int input = -1;
while ((input = scanner.nextInt()) > 0) {
// 创建一个节点
n = new Node(input);
// 头节点的地址赋值给新节点
// 新节点连接到头结点上
n.next = h;
// 以新节点作为新的头结点
h = n;
}
return h;
}

代码执行过程示意图

方法开始执行时,先创建Node的引用变量hn,此时hn并没有引用对象。他们的值都为null,如下图所示:

1
2
3
4
5
6
7
8
9
10
11
/*
1: Node head=null
*/
digraph demo {
rankdir=LR;
node [shape=record];
h [shape=ellipse];
n [shape=ellipse];
n -> null [color="red"];
h -> null [color="red"];
}

用户从键盘输入一个大于0的数字之后,这里假设输入的是1
则会创建一个Node对象,并把该对象的地址赋值给引用变量n.
如下图所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
2: n=new Node(1);
*/
digraph demo {
rankdir=LR;
node [shape=record];
h [shape=ellipse];
n [shape=ellipse];

a [label="{1|}"];

h -> null;
n ->a [color="red"];
}

此时创建的节点是第1个节点,它后面没有旧的节点,所以该节点的地址域应该赋值为null,因为head的值也是null,所以这里设置为head的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
2: Node n=new Node(1);
3: n.next=null,也就是n.next=head
*/
digraph demo {
rankdir=LR;
node [shape=record];
h [shape=ellipse];
n [shape=ellipse];

a [label="{1|null}" color="red"];

h -> null;
n ->a;
}

接下来把这个新创建的直接的地址赋值给头指针h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
2: n=new Node(1);
3: n.next=null,也就是n.next=head
新创建的节点的地址赋值给头指针h
4: h=n;
*/
digraph demo {
rankdir=LR
node [shape=record]
null
h [shape=ellipse]
n [shape=ellipse]
a [label="{1|null}"]
// h -> null

n -> a
h -> a [color="red"]
}

然后,再次创建一个新的节点,地址赋值给引用变量n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
再次创建一个节点,并把地址赋值给指针n
5: n=new Node(2);
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
// null [shape=ellipse]

// h -> null
n -> n2 [color="red"]
h -> n1
}

新创建的节点的地址域记录下链表的头节点的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
把头指针h中保存的地址赋值给新创建的节点的地址域
6: n.next=head;
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]

n -> n2
n2 -> n1 [color="red"]
h -> n1
}

头指针记录新创建的节点的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
把头指针h中保存的地址赋值给新创建的节点的地址域
6: n.next=head
头指针保存新创建的节点的地址
7: h=n;
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]

n1 [label="{1|null}"]
n2 [label="{2|}"]

n -> n2
n2 -> n1
h -> n2 [color="red"]
}

然后在次创建一个新节点,地址记录在指针n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
再次创建一个节点,并把地址赋值给指针n
8: n=new Node(2);
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
n3 [label="{3|}"] [color="red"]

n -> n3 [color="red"]
h -> n2
n2 -> n1
}

新创建的节点的地址域记录头节点的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
再次创建一个节点,并把地址赋值给指针n
8: n=new Node(2);
把头指针h保存的地址赋值给新创建的节点的地址域
9: n.next=h;
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
n3 [label="{3|}"]

n -> n3
n3 -> n2 [color="red"]
n2 -> n1
h -> n2
}

头指针记录下新创建的节点的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
头指针保存新创建的节点的地址
10: h=n;
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
n3 [label="{3|}"]

n -> n3
n3 -> n2
n2 -> n1

h -> n3 [color="red"]
}

再次创建一个新的节点,地址记录在指针n中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
再次创建一个节点,并把地址赋值给指针n
11: n=new Node(3);
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
n3 [label="{3|}"]
n4 [label="{4|}"] [color="red"]

n -> n4 [color="red"]

h -> n3
n3 -> n2
n2 -> n1
}

新创建的节点记录头节点的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
新创建的节点的地址域记录头结点的地址
12: n.next=h;
*/
digraph demo {
rankdir=LR
node [shape=record]
h [shape=ellipse]
n [shape=ellipse]
n1 [label="{1|null}"]
n2 [label="{2|}"]
n3 [label="{3|}"]
n4 [label="{4|}"]

n -> n4
n4 -> n3 [color="red"]
n3 -> n2
n2 -> n1

h -> n3
}

dot学习1

包含一个”hello”的图形

1
2
3
digraph {
hello
}

显示效果

1
2
3
digraph {
hello
}
1
2
3
4
5
6
7
8
9
10
11
![xxx](https://g.gravizo.com/svg?
digraph G {
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf
init -> make_string;
main -> printf;
execute -> compare;
})

这样写时不行的,还需要进行URL编码:

1
![xxx](https://g.gravizo.com/svg?digraph%20G%20%7B%0A%20%20%20%20main%20-%3E%20parse%20-%3E%20execute%3B%0A%20%20%20%20main%20-%3E%20init%3B%0A%20%20%20%20main%20-%3E%20cleanup%3B%0A%20%20%20%20execute%20-%3E%20make_string%3B%0A%20%20%20%20execute%20-%3E%20printf%0A%20%20%20%20init%20-%3E%20make_string%3B%0A%20%20%20%20main%20-%3E%20printf%3B%0A%20%20%20%20execute%20-%3E%20compare%3B%0A%7D)

渲染效果如下:

xxx

调整图形形状

graphviz支持很多的图形形状,完整列表可以参考
https://www.graphviz.org/doc/info/shapes.html

按类别可以分成两类,

  • 一类是正方形、圆形等几何形状,
  • 另一类是表格(Record Node)

几何图形

比如把上面”hello”这个椭圆形改成正方形,使用语法shape=box即可

1
2
3
digraph {
hello [shape=box];
}

显示效果

1
2
3
digraph {
hello [shape=box];
}

表格

1
2
3
digraph {
hello [shape=record label="first|second|last"];
}

显示效果如下

1
2
3
digraph {
hello [shape=record label="first|second|last"];
}

节点关系

定义两个节点

1
2
3
4
digraph {
node1 [shape=box];
node2 [shape=box];
}

显示效果

1
2
3
4
digraph {
node1 [shape=box];
node2 [shape=box];
}

有向图 单向 node1 -> node2

1
2
3
4
5
digraph {
node1 [shape=box];
node2 [shape=box];
node1 -> node2;
}

显示效果:

1
2
3
4
5
digraph {
node1 [shape=box];
node2 [shape=box];
node1 -> node2;
}

有向图 双向 node1 -> node2 node2 -> node1

1
2
3
4
5
6
digraph {
node1 [shape=box]
node2 [shape=box]
node1 -> node2
node2 -> node1
}

显示效果

1
2
3
4
5
6
digraph {
node1 [shape=box]
node2 [shape=box]
node1 -> node2
node2 -> node1
}

无向图 node1 – node2

1
2
3
4
5
graph {
node1 [shape=box]
node2 [shape=box]
node1 -- node2
}

显示效果

1
2
3
4
5
graph {
node1 [shape=box]
node2 [shape=box]
node1 -- node2
}

参考资料

https://juejin.cn/post/6844903942883655687

链表回顾

创建链表的时候,把创建好的链表赋值给this指针。
方法的参数要尽量的少

链表的倒置

image-20210726142352908

明天任务

模拟SQL登陆

栈和队列

先进后出

栈的操作

入栈 push

出栈 pop

取栈顶元素 top

判断栈是否为空 isEmpty

括号匹配问题

输入一个字符串,判断一个字符串中的括号是否都整除的开合。

从左向右扫描,遇到左括号,则入栈,如果遇到右括号,则判断该右括号是否与栈顶的左括号是否匹配
如果不匹配,则退出,如果匹配则继续下一个匹配
如果扫描结束,栈为空,则说明括号匹配

img

课堂习题:使用链表实现一个栈

队列

先进先出

队列可以解决那些问题

使用链表实现一个队列

使用数组实现一个队列

使用循环数组

tail=(tail+1)%size
head=(head+1)%size

如何判断空

使用一个计数器,如果计数器的数值等于数组的长度,那就满了

题目:

使用泛型

  • 数组实现队列 和 堆栈
    • 数组满了,则扩容
  • 链表竖线队列 和 堆栈

SQL专项训练题(一)

(一)数据源情况:以下各题操作表结构如下:

Student(学生表)

字段名 字段类型 说明
sno 文本型 学号,不能存在相同的 主键
sname 文本型 姓名,非空
sex 文本型 性别,只能“男”或“女”
dept 文本型 系别,包括这几个:信息系,计算机科学系,数学系,管理系,中文系,外语系,法学系
birth 日期/时间型 出生日期
age 数值型 年龄,在0~100之间

student(sno,sname,sex,dept,birth,age)

cs(成绩表):

字段名 字段类型 说明
sno 文本型 学号
cno 文本型 课程号
score 数值型 成绩, 只能在0~100之间,可以不输入值

cs(sno,cno,score)

course(课程表)

字段名 字段类型 说明
cno 文本型 课程号, 不能有重复的
cname 文本型 课程名,非空
cval 数值型 学分

course(cno,cname,cval)

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

(二)针对学生课程数据库查询

(1)查询全体学生的学号与姓名。

sno—student
sname—-student

1
2
select sno,sname
from student;

(2)查询全体学生的姓名、学号、所在系,并用别名显示出结果。

sname,sno,dept

1
2
select sname as name,sno as id,dept as 科系
from student;

(3)查询全体学生的详细记录。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
select * from student;

(4)查全体学生的姓名及其出生年份

1
2
select sname,birth
from student;

(5)查询学校中有哪些系。

1
select distinct(birth) from student;

(6)查询选修了课程的学生学号。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
select distinct(sno)
from cs;

(7)查询所有年龄在20岁以下的学生姓名及其年龄。

sno,age—–student

1
2
3
select sname,age
from student
where age<20;

(8)查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。

sname,dept,age—-student

1
2
3
select sanme,dept,age
from student
where age>=20 and age<=23;

(9)查询年龄不在20~23岁之间的学生姓名、系别和年龄。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select sname,dept,age
from student
where age<20 or age>23;

(10)查询信息系、数学系和计算机科学系生的姓名和性别。

1
2
3
select sname,sex
from student
where dept='信息' or dept='数学' or dept='计算机科学';

(11)查询既不是信息系、数学系,也不是计算机科学系的学生的姓名和性别。

1
2
3
select sname,sex
from student
where dept!='信息' and dept!='数学' and dept!='计算机科学';

(12)查询所有姓刘学生的姓名、学号和性别。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select sname,sno,sex
from student
where sname like '刘%';

SQL 通配符

在 SQL 中,通配符与 SQL LIKE 操作符一起使用。

SQL 通配符用于搜索表中的数据。

在 SQL 中,可使用以下通配符:

通配符 描述
% 替代0个或多个字符
_ 替代一个字符
[charlist] 字符列中的任何单一字符
[^charlist][!charlist] 不在字符列中的任何单一字符

(13)查询学号为2009011的学生的详细情况。(具体的学号值根据表中数据确定)

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
selec * from student
where sno='2009011';

(14)查询姓“欧阳”且全名为三个汉字的学生姓名

1
2
select sname from student
where sname like '欧阳__';

(15)查询名字中第2个字为“晨”字的学生的姓名和学号

1
2
3
select sname,sno
from student
where sname like '__晨%';

一个汉字占两个字符

(16)查询所有不姓刘的学生姓名。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select sname
from student
where sname not like '刘%';

SQL NOT运算符

//原文出自【易百教程】,商业转载请联系作者获得授权,非商业转载请保留原文链接:https://www.yiibai.com/sql/sql-not.html#

在前面已经学习了如何使用各种逻辑运算符,如:ANDORLIKEBETWEENINEXISTS。 这些运算符可帮助您在WHERE子句中形成灵活的条件。

要反转任何布尔表达式的结果,请使用NOT运算符。 以下演示如何使用NOT运算符。

1
NOT [Boolean_expression]

(17)查询sql课程的课程号和学分。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select cno,cval
from course
where cname='sql';

(18)查询以”DB_”开头,且倒数第3个字符为 i的课程的详细情况

1
2
select * from course
where cname like 'DB\_%i__' escpe '\';

SQL like如何匹配%和_字符本身

https://www.hegongshan.com/2018/09/19/sql-like/

如果需要查询的匹配字符串本身就含有%和_,可以使用escape '<换码字符>'对通配符进行转义。

示例:

6.查询Algorithms_Design课程的课程号和学分

复制

1
2
3
select cno,credit
from course
where cname like 'Algorithms\_Design' escape '\';

7.查询课程名以“算法_”开头,且倒数第二个汉字为“设”的课程详情。

复制

1
2
3
select *
from course
where cname like '算法\_%设__' escape '\';

注意:换码字符是可以变化的,一般取不常用的符号。若匹配串中本身含有 “ \ ”,则换码字符可取 “ ? ”等。

(19)查询缺少成绩的学生的学号和相应的课程号。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

sno—student表,sc表
cno—cs表

1
2
3
select sno,cno
from cs
where score is null;
1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
4
select sno
from cs
group by sno
having count(*)>3;

(33)查询有3门以上课程是90分以上的学生的学号及(90分以上的)课程数。

sno,count(cno)—-cs表

1
2
3
4
select sno,count(cno) as c_num
from cs
group by sno
having count(*)>=3 and min(score)>=90;

(34)查询学生2006011选修课程的总学分。

1
2
3
4
select sum(score) as total_score
from cs
where sno='2006011'
group by sno;

(35)查询每个学生选修课程的总学分。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select sno,sum(score) as total_score
from cs
group by sno;

(36)查询每个学生及其选修课程的情况。

1
2
3
select sno,sname,cno
from student as s,cs
where s.sno=cs.sno;
1
2
3
4
select sno,sname,cno,cname
from
student as s,cs,course as c
where s.sno=cs.sno and cs.cno=c.cno;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
select sno,sname,cno,cname
from
(select sno,sname from student) as R1
inner join
(
select sno,cno,cname
from(
(select cno,cname from course) as C
inner join
(select sno,cno from cs) as cs2
on c.cno=cs2.cno
)
) as R2
on R1.sno=R2.sno;

(37)查询选修2号课程且成绩在90分以上的所有学生的学号、姓名

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

sno ——-student表
sname —–student表

cno=’2’—-cs表
score>90—cs表

1
2
3
select s.sno,sname
from student as s,cs
where s.sno=cs.sno and cno='2' and score>=90;

子查询实现

1
2
3
4
5
6
7
8
9
select s.sno,sname
from
student as s,
(
select sno
from cs
where cno='2' and score>=90
) as R
where s.sno=R.sno;

子查询找出选项2号课程,并且成绩大于等于90的学生的学号
然后课程表和子查询得到临时表R进行连接
然后从连接表中取出学号和姓名即可

1
2
3
4
5
6
7
8
9
10
11
select s.sno,sname
from
(
select sno,sname from student
) as s,
(
select sno
from cs
where cno='2' and score>=90
) as R
where s.sno=R.sno;

(38)查询每个学生的学号、姓名、选修的课程名及成绩。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

sno,sname,—–student表
cname,—-course表
score—–cs表

1
2
3
select s.sno,sanme,cname,score
from student as s,cs,course as c
where s.sno=cs.sno and cs.cno=c.cno;
1
2
3
4
5
6
7
8
9
10
11
select sno,sname,cname,score
from
(
select sno,sname from student
) as R1,
(
select sno,cname,score
from cs,course as c
where cs.cno=s.cno
) as R2
where R1.sno=R2.sno;
1
2
3
4
5
6
select s1.sno,sname,c1.cname,score
from
(select sno,sname from student) as s1,
(select cno,cname from course) as c1,
cs
where s1.sno=cs.sno and cs.cno=c1.cno;

(39)查询与“刘晨”在同一个系学习的学号和姓名(分别用嵌套查询和连接查询)

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

sname=’刘晨’—student表
dept——-student表
sno—–student表
sname—-student表

1
2
3
4
5
6
select s1.sno,s1.sname
from
student as s1
inner join
student as s2
on s2.sname='刘晨' and s1.dept=s2.dept;

子查询实现

1
2
3
4
5
6
7
8
select sno,sname
from student as s
where dept in
(
select dept
from student as s
where s.sname='刘晨'
);

(40)查询选修了课程名为“信息系统”的学生学号和姓名

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
4
5
6
7
8
9
10
11
12
select sno,sname
from student
where sno in
(
select sno from
cs
where cno in
(
select cno from course
where cname='信息系统'
)
);

(41)查询其他系中比信息系任意一个(其中某一个)学生年龄小的学生姓名和年龄

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
4
5
6
7
8
select sname,age
from student
where dept!='信息' and age < any
(
select age
from student
where dept='信息';
);

(42)查询其他系中比信息系所有学生年龄都小的学生姓名及年龄。

1
2
3
4
5
6
7
select sname,age
from student
where dept!='信息' and age < all(
select age
from student
where dept='信息'
);
1
2
3
4
5
6
7
select sname,age
from student
where dept!='信息' and age < (
select min(age)
from student
where dept='信息'
);

(43)查询所有选修了1号课程的学生姓名。(分别用嵌套查询和连查询)

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

sanme,—student表
cno=’1’—-cs表

嵌套查询

1
2
3
4
5
6
select sname from student
where sno in
(
select sno from cs
where cno='1'
);

连接查询

1
2
3
select sname
from student as s,cs
where s.sno=cs.sno and cs.cno='1';

(44)查询没有选修1号课程的学生姓名。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

子查询

1
2
3
4
5
6
7
select sname from student
where sno in
(
select sno
from cs
where cno!='1'
);

先查询出没有选修1号课程的学生的学号,然后再根据学号选择出姓名

子查询和连接实现

1
2
3
4
5
select sname from
(select sno,sname from student) as R1
inner join
(select sno from cs where cno!='1') R2
on R1.sno=R2.sno;

(45)查询选修了全部课程的学生姓名。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

思路:查询一个学生的姓名,该学生选修课的门数等于所有课程的门数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
select sname from student
where sno in
(
-- 查询出选修课程数量等于课程表中的课程数量相等的学生的学号
select sno from cs
-- 按照学号进行分组
group by sno
-- 统计分组中记录的数量,得到学生选修的课程数量
-- 当学生选修的课程数量等于课程表中的课程数量时,说明该学生选修了所有的课程
having count(*)=(
-- 统计课程表中的课程数量
select count(*) from course
)
);

查询选修了全部课程的学生姓名

https://www.pianshen.com/article/1491914644/
image-20210726165956168

第一种:

理解为:查询一个人的姓名,不存课程 该学生没选修
思路:
1.拿出Student表的第一行数据
2.拿出Course表的第一行数据
3.拿出SC表的第一行数据 (其实这个表就是用来与前两个表进行对比判断的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*查询一个学生的学号 (在Student表中循环取学生信息)*/
SELECT Sname
FROM Student
/*不存在课程 (在Course中循环取所有课程信息)*/ 
WHERE NOT EXISTS(          
  SELECT *
  FROM Course
/*该学生没选修 (在SC表中循环比对) */
  WHERE NOT EXISTS(
    SELECT *
    FROM SC
    WHERE SC.Sno = Student.Sno AND SC.Cno = Course.Cno
  )
);

结果:选择出学生的姓名,这个学生所有课程都选修了

第二种:思路:

查询一个学生的姓名,该学生选修课的门数等于所有课程的门数

逆推:查询一个学生的姓名,姓名怎么来?
  • 通过Student的学号得到,学号怎么得到?
    • 通过在SC表中Sno分组判断该学生的选修的课程门数是否等于所有课程的门数得到,所有课程门数如何得到?
      • 通过在Course表中COUNT(*)得到
        SQL语句:
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        SELECT Sname
        FROM Student
        WHERE Sno in (
          SELECT Sno
          FROM SC
          GROUP BY Sno
        /*该学生的选修的课程门数 = 所有课程的门数*/
          HAVING COUNT(*) = (
        /*所有课程的门数*/
            SELECT COUNT(*)
            FROM Course
          )
        );

要求查询出 :选修了全部课程的学生姓名

https://www.cnblogs.com/losesea/archive/2012/10/10/2718093.html

例子: 三张表 学生表student(Sno,Sname), 课程表course(Cno,Cname) 选课表SC(Sno,Cno)

  • 首先,学生的选课信息存在于SC表中, 要想知道某个学生是否选修了全部课程,至少我们需要知道一共有几门课程,这是首要的条件。
  • 其次,学生选修了与否,我们又要扫描SC全表,统计出选修了所有课程的学生号,
  • 最后,在STUDENT表中根据学生号打出姓名 。
1
2
3
4
5
6
7
8
9
10
11
12
13
select Sname from student             
where Sno IN
(
select Sno from SC
-- 根据学号Sno分组,
group by Sno
-- 统计每个学生选修了几门课程。
-- 如果该学生选课数量,等于course的总数,则说明该学生选修了所有的课程,就是我们要找的Sno
having count(*) = (
-- 统计course中共有几门课程
select count(*) from course
)
);

(46)查询至少选修了学生95002选修的全部课程的学生号码。

需要使用相干子查询

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)

选出这样的学生X, 不存在这样一门课Y, 学生95002选了而学生X没有选

不存在这样一门课,学生95002选了,学生x没有选

select sno from cs
where not exists(
select cno
from cs as
where not exists(
select from cs where sno=’95002’ and ;
)
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
select distinct x.sno
-- 对于学生x
from sc as x
-- 不存在
where not exists(
select *
from sc as y
-- 这样一门课, 95002选了,x没有选
where y.sno = '95002' and not exists(
select *
from sc as z
-- 课程 y, x没选
where z.cno = y.cno and z.sno = x.sno
)
);
;

(47)查询选修了学生95002选修的课程完全一致的学生学号

(48)查询计算机科学系的学生及年龄不大于19岁的学生的信息。

(49)查询选修了课程1或者选修了课程2的学生的信息。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
4
5
6
7
select * from student
where sno in
(
select sno
from cs
where cno='1' or cno='2'
);

(50)查询计算机科学系中年龄不大于19岁的学生的信息。

1
2
select * from student
where dept='计算机' and age<=19;

(51)查询既选修了课程1又选修了课程2的学生的信息。

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
4
5
6
select * from student
where sno in(
select C1.sno
from cs as C1,cs as C2
where C1.sno=C2.sno and C1.cno='1' and C2.cno='2'
);

(52)通过查询求学号为1学生的总分和平均分。

1
2
3
4
select sum(score) as total_score,avg(score) as avg_score
from cs
group by sno
having sno='1';

(53)求出每个系的学生数量

1
2
3
student(sno,sname,sex,dept,birth,age)
course(cno,cname,cval)
cs(sno,cno,score)
1
2
3
select dept,count(sno) as student_nums
from student
group by dept;

(54)查询平均成绩大于85的学生学号及平均成绩。

1
2
3
4
select sno,avg(score)
from sc
group by sno
having avg(score)>85;

(55)要求查寻学生的所有信息,并且查询的信息按照年龄由高到低排序,如果年龄相等,则按照学号从低到高排序

1
2
select * from student
order by age desc,sno asc;

3.4 SQL数据更新

SQL语言的数据更新语句DML主要包括插入数据、修改数据和删除数据三种语句。

3.4.1 插入数据记录

插入数据是把新的记录插入到一个存在的表中。插入数据使用语句INSERT INTO,可分为以下几种情况。

3.4.1.1 插入一行新记录

语法格式为:

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

其中,

  • <表名>是指要插入新记录的表
  • <列名>是可选项,指定待添加数据的列
  • VALUES子句指定待添加数据的具体值。