欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据库查询进阶--连接查询

程序员文章站 2024-03-23 09:14:34
...

#a.左外联接
#语法:SELECT 表1.字段,表2.字段 FROM 表1 LEFT JOIN 表2 ON 表1.字段x = 表2.字段y;
#查询参加考试的学员名单(成绩表中有成绩的学员)
SELECT 
	students.studentNo AS 学员编号,
	studentName AS 学员姓名,
	studentResult AS 学员成绩
FROM results
LEFT JOIN students ON students.studentNo = results.studentNo;

#查询每位同学的成绩
SELECT 
	students.studentNo AS 学员编号,
	studentName AS 学员姓名,
	studentResult AS 学员成绩
FROM students
LEFT JOIN results ON students.studentNo = results.studentNo;

#b.右外联接
#语法:SELECT 表1.字段,表2.字段 FROM 表1 RIGHT JOIN 表2 ON 表1.字段x = 表2.字段y;
#查询参加考试的学员名单(成绩表中有成绩的学员)
SELECT 
	students.studentNo AS 学员编号,
	studentName AS 学员姓名,
	studentResult AS 学员成绩
FROM students
RIGHT JOIN results ON students.studentNo = results.studentNo;

#查询每个年级的科目信息
SELECT
	grades.gradeId AS 年级编号,
	gradeName AS 年级名称,
	subjectNo AS 科目编号,
	subjectName AS 科目名称
FROM grades
LEFT JOIN subjects 	ON 	grades.gradeId = subjects.gradeId;
#右外联接
SELECT
	grades.gradeId AS 年级编号,
	gradeName AS 年级名称,
	subjectNo AS 科目编号,
	subjectName AS 科目名称
FROM subjects
RIGHT JOIN grades ON 	grades.gradeId = subjects.gradeId;

1.左连接查询的使用:

数据库查询进阶--连接查询

#创建数据库bank
create database bank;
#选中数据库bank
use bank;
#创建银行卡表,一般余额使用double或者decemial
create table card(
cardid int not null comment'银行卡号',
balance int not null comment '余额'
)comment'银行卡表';
#创建用户表
create table user(
userid int not null comment'用户id',
username varchar(20) not null comment'用户姓名',
cardid int not null COMMENT'银行卡号'
)COMMENT'用户表';
insert into card
values(10001,10),
		  (10002,2000);
			
insert  user 
values(1,'A',10001),
		 (2,'B',10002),
		 (3,'C',10003),
		 (4,'D',10004);

#步骤:
#1.查出删除的两张卡
#2.将查到的卡插入card表,设置余额值为3

#z左连接
#方式1用not in
insert into card 
select cardid,3 from user
where cardid
not in(select user.cardid
from card 
left join user on card.cardid = user.cardid)

#方式2,用连接后是否为空值筛选
insert into card 
select user.cardid,3 from user left join card on user.cardid=card.cardid where card.cardid is null

2.右联接查询:

与左连接查询相似,可以理解为将左连接查询的两张表顺序交换,同样是上表。

insert into card 
select user.cardid,3 from card right join user on user.cardid=card.cardid where card.cardid is null

3.内连接查询

#SELECT 表1.字段,表2.字段 FROM 表1 INNER JOIN 表2 ON 表1.字段x = 表2.字段y;
#查询学员的【学员编号,姓名,年级编号,年级名称】信息
SELECT 
	studentNo AS 学员编号,
	studentName AS 学员姓名,
	students.gradeId AS 年级编号,
	gradeName AS 年级名称
FROM students
INNER JOIN grades	ON students.gradeId = grades.gradeId;

#从两个表中检索数据
SELECT 
	studentNo AS 学员编号,
	studentName AS 学员姓名,
	students.gradeId AS 年级编号,
	gradeName AS 年级名称
FROM students,grades
WHERE students.gradeId = grades.gradeId;

4.自连接查询:

自连接就是本行的某个字段是另一行的一个属性。如,,小米的pid为2,2是手机的id。

#建表
create table if not exists categries
(
id int(4) not null auto_increment comment'类别编号',
name varchar(50) not null comment'类别名称',
pid int(4) not null default 0 comment'父类编号',
constraint PK_id primary key(id)
)comment'类别表';
#数据插入
insert into categries(id,name,pid)
values(1,'计算机',0),
       (2,'手机',0),
       (3,'DELL',1),
			 (4,'Lenovo',1),
			 (5,'ASUS',1),
			 (6,'HUAWEI',2),
			 (7,'小米',2), 
			 (8,'OPPO',2);
#查看插入数据
select * from categries		

#自连接的使用	 
select 
  a.id as 父类编号,
  a.name as 父类名称,
	b.id as 子类编号,
	b.name as 子类名称
from categries as a
join categries as b on a.id = b.pid;
#NATURAL JOIN
SELECT 
			gradeId as 年级编号,
			gradeName as 年级名称,
			studentNo as 学号,
			studentName as 姓名
	FROM grades
	NATURAL JOIN students;
	
#使用USING子句
	SELECT 
			gradeId as 年级编号,
			gradeName as 年级名称,
			studentNo as 学号,
			studentName as 姓名
	FROM grades
	JOIN students USING(gradeId); 
	
#查询参加考试的学员的每门课程的成绩(多表联接)
SELECT results.subjectNo as 课程编号,
       subjectName as 课程名称,
       results.studentNo as 学号,
       studentName as 姓名,
       studentResult as 成绩
FROM results
JOIN subjects ON subjects.subjectNo = results.subjectNo
JOIN students ON students.studentNo = results.studentNo;

#使用AND 子句或WHERE 子句可应用附加条件:
  #AND
	SELECT results.subjectNo as 课程编号,
	       subjectName as 课程名称,
	       results.studentNo as 学号,
	       studentName as 姓名,
	       studentResult as 成绩
	FROM results
	JOIN subjects ON subjects.subjectNo = results.subjectNo
	JOIN students ON students.studentNo = results.studentNo
	AND results.subjectNo = 1;
 #WHERE(常用)
	SELECT results.subjectNo as 课程编号,
	       subjectName as 课程名称,
	       results.studentNo as 学号,
	       studentName as 姓名,
	       studentResult as 成绩
	FROM results
	JOIN subjects ON subjects.subjectNo = results.subjectNo
	JOIN students ON students.studentNo = results.studentNo
	WHERE results.subjectNo = 1;
	


# 交叉联接
SELECT 
				grades.gradeId as 年级编号,
        gradeName as 年级名称,
        subjectNo as 课程编号,
				subjectName as 课程名称
FROM grades
CROSS JOIN subjects;

SELECT 
				grades.gradeId as 年级编号,
        gradeName as 年级名称,
        subjectNo as 课程编号,
				subjectName as 课程名称
FROM grades,subjects;


#子查询
#查询姓名为张三的考试成绩
  #步骤一:在学员表中,查询姓名为张三的学号
	SELECT studentNo FROM students WHERE studentName='张三';#1004
  #步骤二:在成绩表中查询学号为1004的成绩
	SELECT * FROM results WHERE studentNo = 1004;
#使用子查询完成(使用关系运算符时,确保子查询的结果为单行单列)	
SELECT * FROM results WHERE studentNo=(SELECT studentNo FROM students WHERE studentName='张三');
#建议如下操作(如果子查询的结果为多行单列时,常使用IN子查询)
SELECT * FROM results WHERE studentNo IN(SELECT studentNo FROM students WHERE studentName like '李%');

#查询科目编号为1的学员成绩且成绩大于90
SELECT 
	studentResult as 成绩
FROM results WHERE subjectNo=1 AND studentResult>90;

#在成绩表中查询 任意 小于等于(科目编号为1的学员成绩且成绩大于90) 成绩信息
SELECT * FROM results 
WHERE studentResult <= ANY (SELECT 
	studentResult as 成绩
FROM results WHERE subjectNo=1 AND studentResult>90);

SELECT * FROM results 
WHERE studentResult <= ALL (SELECT 
	studentResult as 成绩
FROM results WHERE subjectNo=1 AND studentResult>90);

#使用EXISTS 运算符:
   #查询参加考试的学员信息。
	 #EXISTS子句中如果有记录返回True,如果没有记录返回false
  SELECT * FROM students WHERE EXISTS(
	SELECT * FROM results WHERE students.studentNo = results.studentNo);
	
	SELECT * FROM students WHERE 1=1;
	
#案例
CREATE TABLE IF NOT EXISTS game
(
	id INT(4) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	password VARCHAR(20) NOT NULL
)COMMENT='游戏卡表';
#插入数据
INSERT INTO game(password) VALUES('abcoooiiiabc'),('ooiiabcooii'),('helloabciii');
#查询表中的数据
SELECT * FROM game;
#更新数据
UPDATE game SET password=REPLACE(password,'o','0');
UPDATE game SET password=REPLACE(password,'i','1');
#一条语句完成
UPDATE game SET password=REPLACE(REPLACE(password,'o','0'),'i','1');

#排序
/*
SELECT 列名,列名,...
FROM 表名
ORDER BY 表达式;
*/
#查询科目编号为1的学员成绩,并按由高到低排序
SELECT 
	subjectNo AS 科目编号,
	studentNo AS 学员编号,
	studentResult AS 成绩
FROM results
WHERE subjectNo = 1
ORDER BY studentResult DESC; #descending 降序

SELECT 
	subjectNo AS 科目编号,
	studentNo AS 学员编号,
	studentResult AS 成绩
FROM results
WHERE subjectNo = 1
ORDER BY studentResult ASC; #ascending默认为升序排序

#按多列排序,成绩相同的按学号排序
SELECT 
	subjectNo AS 科目编号,
	studentNo AS 学员编号,
	studentResult AS 成绩
FROM results
WHERE subjectNo = 1
ORDER BY studentResult,studentNo DESC;

/*
任务:将数据库表NumTab中的num列中的数据
       11-101,11-11,12-1,11-110,12-104,101-1先按减号前半部分排序,
	再按减号后面部分排序。
*/
#创建表
	DROP TABLE IF EXISTS NumTab;
	CREATE TABLE IF NOT EXISTS NumTab
	(
			id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
			num varchar(20) NOT NULL
	);
	#插入数据
	INSERT INTO numtab(num)
		VALUES
			('11-101'),
			('11-11'),
			('101-1'),
			('12-1'),
			('11-110'),
			('12-104');
	#查询所有数据
	SELECT * FROM numtab;
	#求-号的位置
	SELECT INSTR(num,'-') from numtab;
	#求-号前面的内容
	SELECT SUBSTRING(num,1,INSTR(num,'-')-1) FROM numtab;
	#求-号后面的内容
	SELECT SUBSTRING(num,INSTR(num,'-')+1) FROM numtab;
	#按-号前面内容排序
	SELECT * FROM numtab ORDER BY convert(SUBSTRING(num,1,INSTR(num,'-')-1),SIGNED);
	#按-号前面内容排序,再按-号后面的排序
	SELECT * FROM numtab 
		ORDER BY 
		convert(SUBSTRING(num,1,INSTR(num,'-')-1),SIGNED),
		convert(SUBSTRING(num,INSTR(num,'-')+1),SIGNED);
		
		
#统计参加考试的学员人数
SELECT COUNT(DISTINCT studentNo) AS 学员人数 FROM results;
#求总成绩、平均成绩、最高成绩和最低成绩
	 SELECT 
		SUM(studentResult) as 总成绩,
		AVG(studentResult) as 平均成绩,
		MAX(studentResult) as 最高成绩,
		MIN(studentResult) as 最低成绩
	FROM
		results;
		
#分组查询,统计每个年级的学员人数
	SELECT 
		gradeId as 年级编号,
		count(*) as 学员人数 
	FROM students
	GROUP BY gradeId;
#统计每个科目的平均成绩
 SELECT 
	subjectNo as 科目编号,
	AVG(studentResult) as 学员成绩
 FROM results 
 GROUP BY subjectNo;
 
 #统计每个年级下的每个性别的学员人数
	SELECT 
		gradeId as 年级编号,
		sex as 性别,
		count(studentNo) as 学员人数 
	FROM students
	GROUP BY gradeId,sex;
	
	
#分组之后再进行筛选,使用having子句
#统计每个年级的学员人数且总人数必须大于等于4
	SELECT 
		gradeId as 年级编号,
		count(*) as 学员人数 
	FROM students
	GROUP BY gradeId
	HAVING count(*)>=4;
	
#查询成绩表中的数据,要求每页显示8条记录,显示第1页数据 和 第8页数据
SELECT * FROM results LIMIT 0,8; #第1页数据
SELECT * FROM results LIMIT 56,8; #第8页数据 起始位置=(页码-1)*记录数
相关标签: # Mysql