数据查询(where),多表查询,多表关联,内外连接,子查询(二)

3,325 阅读8分钟

1 数据查询(重要)

​ 所有查询都不会改变表中的数据

(1)关键字distinct

​ 去重

select distinct(【列名】price) from 【表名】product

只显示去重了的列。

(2)查询中可以带有计算,查询所有数据,每个商品的价格提升10%

select pid,pname,category,price*0.1 + price,category_id from product

(3)查询结果重命名 关键字as

select pid,pname,category,price*0.1 + price as 'price',category_id from product

(4)查询结果重命名简化写法

去掉as 去掉'' 直接写重命名。

select pid,pname,category,price*0.1 + price price,category_id from product

(5)条件查询where

# 查询商品价格>3000的商品
SELECT * FROM product WHERE price > 3000;

#查询pid=1的商品
SELECT * FROM product WHERE pid = 1;

# 查询pid<>1的商品
SELECT * FROM product WHERE pid <> 1; 

#查询价格在30006000之间的商品,建议使用between
SELECT * FROM product WHERE price >= 3000 AND price <= 6000
# between 只能前面的数字小,前面日期早
SELECT * FROM product WHERE price BETWEEN 3000 AND 6000 

#查询pid在15715范围内的商品
SELECT * FROM product WHERE pid = 1 OR pid = 5 OR pid =7 OR pid = 15

#推荐使用in查询
SELECT * FROM product WHERE pid IN(7,1,5,15)

# 查询商品名以香开头的商品(香系列) 模糊查询 关键字 like
# 查询通配符, % 匹配任意个字符
SELECT * FROM product WHERE pname LIKE '香%'

# 查询商品名包含花 就行
SELECT * FROM product WHERE pname LIKE '%n%'

# 查询商品名以香开头的商品,必须5个字
# 查询通配符, _ 匹配一个字符
SELECT * FROM product WHERE pname LIKE '香____'

(6)分组查询group by

/*
  分组查询  group by
*/

# 按照商品分类,进行价格的求和,
# 商品分类是最后一个列 category_id 进行分组
# category_id列的值,相同的视为一个组,分组统计
SELECT SUM(price),category_id FROM product
GROUP BY category_id

# 追加要求:总价格,小于1000的不想要
/*
  where 作用是条件过滤,只能作用于原始数据表
  having 作用是条件过滤,可以过滤出分组后的临时数据
*/
SELECT SUM(price) `sum`,category_id FROM product
GROUP BY category_id HAVING `sum`>=1000

(7)排序查询 order by

/*
  排序查询 关键字 order by
  升序排列 关键字 asc  默认,可以不写
  降序排列 关键字 desc
*/

# 查询商品表,价格升序排序  
SELECT * FROM product ORDER BY price

# 查询商品表,价格升序排序
SELECT * FROM product ORDER BY price DESC

# 多列排序 第一个列值相等,排第二个列
 
SELECT * FROM product ORDER BY price, pid ASC 


# 查询商品表,价格升序排序,条件价格必须大于等于800
SELECT * FROM product WHERE price >= 800 ORDER BY price

(8)聚合函数

count 统计个数

max 最大值

min 最小值

avg 平均值

sum 总和

注意:聚合函数在进行计算时会忽略null值

# count函数,统计出product 表中的数据有多少条
SELECT COUNT(*) FROM product;

SELECT COUNT(pid) FROM product;

SELECT COUNT(1) `count` FROM product;

# sum函数,计算出所有商品的总价格
SELECT SUM(price) FROM product

# 数学函数,不是数字的列,全部按0计算
SELECT SUM(pname) FROM product

# 计算出商品表中的最大价格
SELECT MAX(price)FROM product

# 计算出所有商品的价格的平均数
SELECT AVG(price) FROM product

2 自增auto_increment

​ 只能给主键加,且得是数据类型。

​ 它的作用是,向数据库中插入数据时,如果没有指定主键的值,它会从0开始为主键赋值

create table student(
	id int primary key auto_increment,
    name varchar(20),
    garde varchar
) 

3 外键约束references

(1)结论:

​ 主表中存在的数据,从表可以存在,可以不存在;

​ 主表中不存在的数据,从表就不能存在。

(2)语法

#学生表
create table student(
	id int primary key auto_increment,
    name varchar(20),
    garde varchar
) 
#成绩表,引用外键
create table score(
	id int primary key auto_increment,
    score double,
    student_id int
)
#添加外键
alter table score add constraint fk_student_id foreign key(student_id) references student(id);

注意:

添加外键时,这个外键一定得是别的表的主键。否则会报错误。

(3)要求

  • 在从表上建立外键,而且主表要先存在。

  • 一个表可以建立多个外键约束

  • 通常情况下,从表的外键列一定要指向主表的主键列

  • 从表的外键列与主表被参照的列名字可以不相同,但是数据类型必须一样

(4)级联删除cascade

​ 它的意思是如果主表删除了一条数据,那么与所有从表中的与这条数据相关的都会跟着删除。

(5)删除外键约束的语法

ALTER TABLE 表名称 DROP FOREIGN KEY 外键约束名;
#查看约束名 SELECT * FROM information_schema.table_constraints WHERE table_name = '表名称';
#删除外键约束不会删除对应的索引,如果需要删除索引,需要用ALTER TABLE 表名称 DROP INDEX 索引名;
#查看索引名 show index from 表名称;

4 多表关系

(1)一对一(了解)

​ 分类:在一对多关系中主表的一行数据可以对应从表的多行数据,反之从表的一行数据则只能对应主表的一行数据。这种一行数据对应一行数据的关系,我们可以将其看作一对一关系。

​ A表中的一行数据对应B表中的一行数据,反之B表中的一行数据也对应A表中的一行数据,此时我们可以将A表当做主表B表当做从表,或者是将B表当做主表A表当做从表。

​ 原则:在从表中指定一个字段创建外键并指向主表的主键,然后给从表的外键字段添加唯一约束。

(2)一对多

​ 概念:主表的一行数据可以同时对应从表的多行数据,反过来就是从表的多行数据指向主表的同一行数据。

添加外键:

从从表中指定一个字段创建外键并指向主表的主键,然后主表会给从表的外键字段添加唯一约束。

​ 场景:分类表和商品表、班级表和学生表、用户表和订单表等等

​ 原则:将一的一方作为主表,多的一方作为从表,在从表中指定一个字段作为外键,指向主表的主键。

-- 创建分类表
CREATE TABLE category(
	cid INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(50)
);

-- 创建商品表
CREATE TABLE product(
	pid INT PRIMARY KEY AUTO_INCREMENT,
	pname VARCHAR(50),
	price DOUBLE,
	cid INT
)
-- 给商品表添加一个外键
alter table product add foreign key(cid) references  category(cid)

(3)多对多

​ 概念:两张表都是多的一方,A表的一行数据可以同时对应B表的多行数据,反之B表的一行数据也可以同时对应A表的多行数据

​ 场景:订单表和商品表、学生表和课程表等等

​ 原则:因为两张表都是多的一方,所以在两张表中都无法创建外键,所以需要新创建一张中间表,在中间表中定义两个字段,这俩字段分别作为外键指向两张表各自的主键。

-- 创建学生表
CREATE TABLE student(
	sid INT PRIMARY KEY AUTO_INCREMENT,
	sname VARCHAR(50)
);

-- 创建课程表
CREATE TABLE course(
	cid INT PRIMARY KEY AUTO_INCREMENT,
	cname VARCHAR(20)
);

-- 创建中间表
CREATE TABLE s_c_table(
	sno INT,
	cno INT
);
-- 给sno字段添加外键指向student表的sid主键
ALTER TABLE s_c_table ADD CONSTRAINT fkey01 FOREIGN KEY(sno) REFERENCES student(sid);
-- 给cno字段添加外键指向course表的cid主键
ALTER TABLE s_c_table ADD CONSTRAINT fkey03 FOREIGN KEY(cno) REFERENCES course(cid);

5 多表关联查询

​ 多表关联查询是使用一条SQL语句,将关联的多张表的数据查询出来。

(1)交叉查询

​ 它的结果是两个表的笛卡尔积。也就是两个表的任意组合,大多数情况下都用不到。

①语法

select a.列,a.列,b.列,b.列 from a,b ;  

select a.*,b.* from a,b ;  
--或者 
select * from a,b;

②示例

select * from t_category,t_product;

③笛卡尔积

​ 假设集合A={a,b},集合B={0,1,2},则两个集合的笛卡尔积为{(a,0),(a,1),(a,2),(b,0),(b,1),(b,2)}。可以扩展到多个集合的情况。

(2)内连接查询

​ 如果想要返回一个两个表具有某种关联关系的结果,我们要用where来声明这个条件,然后让这两个表连接在”一个新的表“(结果)里。

①隐式内连接查询(没有inner join)

select [字段,字段,字段] from a,b where 连接条件 (b表里面的外键 = a表里面的主键 ) 

②显式内连接查询(有inner join)

select [字段,字段,字段] from a [inner] join b on 连接条件 [ where 其它条件]

③内连接查询特点:

​ 主表和从表中的数据都是满足连接条件才能够查询出来,不满足连接条件是不会被查询出来的。

在开发环境中的表名一般都比较复杂,我们可以给这些表在查询语句中声明它们的别名,然后在where中使用别名.列名来声明条件。

(3)外连接查询

①左外连接查询

Ⅰ概念

​ 以join左边的表为主表,展示主表的所有数据,根据条件查询连接右边表的数据,若满足条件则展示,若不满足以null显示。可以理解为:在内连接的基础上保证左边表的数据全部显示

Ⅱ语法
select 字段 from a left [outer] join b on 条件;
Ⅲ示例
select * from t_category c left outer join t_product p on c.cid = p.cno

②右外连接查询

Ⅰ概念

​ 以join右边的表为主表,展示右边表的所有数据,根据条件查询join左边表的数据,若满足则展示,若不满足则以null显示。可以理解为:在内连接的基础上保证右边表的数据全部显示

Ⅱ语法
select 字段 from a right outer join b on 条件
Ⅲ示例
select * t_category c right outer join t_product p on c.cid = p.cno 

6 union联合查询实现全外连接查询

语法

查询语句1 union 查询语句2 union 查询语句3 ...

示例

#用左外的A union 右外的B
select * from t_category c left outer join t_product p on c.cid = p.cno
union
select * from t_category c right outer join t_product p on c.cid = p.cno;

7 子查询

定义

​ 如果一个查询语句嵌套在另一个查询语句里面,那么这个查询语句就称之为子查询,根据位置不同,分为:where型,from型,exists型

​ 注意:不管子查询在哪,子查询必须都得使用()括起来。

作用:

(1)子查询作为另一个查询的条件

(2)子查询作为另一个表