mysql查询DQL&多表关系

文章目录

  • 一.SQL语句(DQL)
    • 1.1 DQL准备工作和语法
      • 1.1.1 准备工作
      • 1.1.2 语法
    • 1.2 简单查询
    • 1.3 条件查询
    • 1.4 排序查询
    • 1.5 聚合查询
    • 1.6 分组查询
  • 二.SQL备份与恢复
    • 2.1 SQL备份
      • 2.1.1 MySQL命令备份
      • 2.1.2 可视化工具备份
    • 2.2 SQL恢复
      • 2.2.1 MySQL命令恢复
      • 2.2.2 可视化工具恢复
  • 三.多表操作
    • 3.1 表与表之间的关系
    • 3.2 外键约束
    • 3.3 一对多
      • 3.3.1 分析
      • 3.3.2 实现:分类和商品
      • 3.3.3 操作
    • 3.4 多对多
      • 3.4.1 分析
      • 3.4.2 实现:订单和商品
      • 3.4.3 操作
    • 3.5 一对一(了解)
    • 3.6 自关联1对多关系(了解)
  • 四:扩展(分页查询)

一.SQL语句(DQL)

1.1 DQL准备工作和语法

1.1.1 准备工作

  1. sql代码建表

    #创建商品表:
    create table product(
    pid int primary key,
    pname varchar(20),
    price double,
    category_id varchar(32)
    );
    
  2. sql代码添加数据

    INSERT INTO product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
    INSERT INTO product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
    INSERT INTO product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');
    INSERT INTO product(pid,pname,price,category_id) VALUES(4,'JACK JONES',800,'c002');
    INSERT INTO product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
    INSERT INTO product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002');
    INSERT INTO product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');
    INSERT INTO product(pid,pname,price,category_id) VALUES(8,'香奈儿',800,'c003');
    INSERT INTO product(pid,pname,price,category_id) VALUES(9,'相宜本草',200,'c003');
    INSERT INTO product(pid,pname,price,category_id) VALUES(10,'面霸',5,'c003');
    INSERT INTO product(pid,pname,price,category_id) VALUES(11,'好想你枣',56,'c004');
    INSERT INTO product(pid,pname,price,category_id) VALUES(12,'香飘飘奶茶',1,'c005');
    INSERT INTO product(pid,pname,price,category_id) VALUES(13,'果9',1,NULL);
    

1.1.2 语法

  1. 查询格式:

    select [distinct]
    * | 列名,列名
    fromwhere 条件
    

1.2 简单查询

  1. 练习

    • 查询所有的商品.

      -- 格式一:查询所有列的数据
      		select 列出所有的列 from 表名;
      		select * from 表名;
      -- 实现1:查询商品名称和商品价格的所有信息
      select * from product;
      
    • 查询商品名和商品价格.

      -- 格式二:查询指定的列
      	select 列名1,列名2... from 表名;
      -- 实现1:查询商品名称和商品价格的所有信息
      select pname,price from product;
      
    • 别名查询.使用的关键字是as(as可以省略的).表别名:

      -- 格式三:别名查询
      	-- 1.给表起别名:多表查询时使用
      		select *|字段 from 表名 [as] 别名;
      -- 实现1:给表起别名:多表查询时使用,简化表的名字
      select * from product as p;
      -- 实现2:给表起别名:多表查询时使用,简化表的名字
      select * from product p;
      
    • 别名查询.使用的关键字是as(as可以省略的).列别名:

      -- 格式四:给表中的字段起别名
      		select 字段1 [as] 别名,...字段n [as] 别名 from 表名;
      -- 实现1:给表中的字段起别名
      select pname as pn,price as pi from product as p;
      -- 实现2:给表中的字段起别名
      select pname pn,price pi from product p;
      
      • 别名查询注意事项:
        • 别名只是对查询的结果临时起一个名字,不会改变表中原有的名字
        • 别名中如果有特殊符号或者空格,那么必须使用引号包裹起来
    • 去掉重复值.

      -- 格式五:过滤重复的数据
      		select distinct 字段1,字段2.. from 表名;
      --	注意:
      		distinct 关键字之后只有一个字段,那么就会过滤掉这个字段中重复的数据
      		distinct 关键字之后如果有多个字段,那么多个字段必须同时满足才会过滤掉
      -- 实现1:查询商品价格,过滤掉重复的价格
      select distinct price from product;
      -- 实现2:查询商品名称和价格,过滤调用名称和价格同时重复的数据
      select distinct pname,price from product;
      
    • 查询结果是表达式(运算查询):将所有商品的价格+10元进行显示.

      -- 格式五:查询语句中,可以直接进行数据计算
      	SELECT (1+1); -- 2
      	SELECT (5/2); -- 2.5000
      select pname,price+10 from product;
      

1.3 条件查询

  1. 运算表格:

    比较运算符 < <= = >= <> 小于、小于等于、等于、大于等于、不等于
    BETWEEN…AND… 显示在某一区间的值(含头含尾)
    IN(set) 显示在in列表中的值,例:in(100,200)
    LIKE ‘张 pattern’ 模糊查询,Like语句中,% 代表零个或多个任意字符,_ 代表一个字符, 例如: first_name like ‘_a%’;
    IS NULL 判断是否为空
    逻辑运行符 and 多个条件同时成立
    or 多个条件任一成立
    not 不成立,例: where not(salary>100);
  2. 练习:

    • 查询商品名称为“花花公子”的商品所有信息:

      SELECT * FROM product WHERE pname='花花公子';
      
    • 查询价格为800商品

      SELECT * FROM product WHERE price = 800;
      
    • 查询价格不是800的所有商品

      SELECT * FROM product WHERE price <> 800;
      SELECT * FROM product WHERE price != 800;
      SELECT * FROM product WHERE NOT (price = 800);
      
    • 查询商品价格大于60元的所有商品信息

      SELECT * FROM product WHERE price > 60;
      
    • 查询商品价格在200到1000之间所有商品

      使用 between...and 优化sql语句
      --	注意:
      	--	1.小的值要写在前边,大的值写后边
      	--	2.可以对时间的区间进行查询  '2019-01-01' 到 '2018-10-6'
      SELECT * FROM product WHERE price>=200 && price<=1000;
      SELECT * FROM product WHERE price BETWEEN 200 AND 1000;
      SELECT * FROM product WHERE price BETWEEN 1000 AND 200;
      
    • 查询商品价格是200或800的所有商品

      -- 使用in(...)优化,简化代码
      SELECT * FROM product WHERE price=800 OR price=200;
      SELECT * FROM product WHERE price IN(200,800);
      SELECT * FROM product WHERE price IN(200,800,1000,2000,3000,4000,5000);
      
    • 查询含有’霸’字的所有商品

      -- 模糊查询:使用关键字like
      	--		%:多个任意字符
      	--		_:1个任意字符
      SELECT * FROM product WHERE pname LIKE '%霸';
      
    • 查询以’香’开头的所有商品

      SELECT * FROM product WHERE pname LIKE '香%';
      
    • 查询第二个字为’想’的所有商品

      SELECT * FROM product WHERE pname LIKE '_想%';
      
    • 商品没有分类的商品

      SELECT * FROM product WHERE category_id IS NULL;
      
    • 查询有分类的商品

      SELECT * FROM product WHERE category_id IS NOT NULL;-- 是不空
      SELECT * FROM product WHERE NOT(category_id IS NULL);
      

1.4 排序查询

  1. 通过 order by 语句,可以将查询出的结果进行排序。暂时放置在select语句的最后。

    • 格式:

      SELECT * FROM 表名 ORDER BY 排序字段 ASC|DESC;
      ASC 升序 (默认)
      DESC 降序
      
    • 练习:

      • 使用价格排序(升序)
             SELECT * FROM product ORDER BY price ASC;
             SELECT * FROM product ORDER BY price;
    
  • 使用价格排序(降序)

       SELECT * FROM product ORDER BY price DESC;
    
  • 在价格排序(降序)的基础上,以分类排序(降序)

    SELECT * FROM product ORDER BY price DESC,category_id DESC;
    
    • 显示商品的价格(去重复),并排序(降序)
    SELECT DISTINCT price FROM product ORDER BY price DESC;
    

1.5 聚合查询

  1. 之前我们做的查询都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。

  2. 今天我们学习如下五个聚合函数:

    • count:统计指定列不为NULL的记录行数;

    • sum:计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;

    • max:计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算;

    • min:计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;

    • avg:计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;

    • 格式:

      select count(字段|*),sum(字段),max(字段),min(字段),avg(字段) from 表名;
      
  3. 练习:

    • 查询商品的总条数

      SELECT COUNT(pid) FROM product; -- 13
      SELECT COUNT(pname) FROM product; -- 13
      SELECT COUNT(category_id) FROM product;-- 12
      SELECT COUNT(*) FROM product; -- 13
      
    • 查询价格大于200商品的总条数

      SELECT COUNT(*) FROM product WHERE price >200; -- 7
      
    • 查询商品的总金额

      SELECT SUM(price) FROM product; -- 17503
      
    • 查询分类为’c001’的所有商品价格的总和

      SELECT SUM(price) FROM product WHERE category_id='c001'; -- 1300
      
    • 查询商品的平均价格

      SELECT AVG(price) FROM product; -- 1346.3846153846155
      
    • 查询分类为’c002’所有商品的平均价格

      SELECT AVG(price) FROM product WHERE category_id='c002';
      
    • 查询商品的最大价格和最小价格

      SELECT MAX(price),MIN(price) FROM product;
      
    • sum,avg如果指定列类型不是数值类型,那么计算结果为0

      SELECT SUM(pname),AVG(pname) FROM product; -- 0,0
      

1.6 分组查询

  1. 分组查询是指使用 group by 字句对查询信息进行分组。

    • 格式:

      SELECT 字段1,字段2FROM 表名 GROUP BY分组字段 HAVING 分组条件;
      
    • 注意:被分组的字段,一般都写在select语句的后边,作为查询条件,方便查看结果

  2. 分组操作中的having子语句,是用于在分组后对数据进行过滤的,作用类似于where条件。

    • havingwhere 的区别:
      • having 是在分组后对数据进行过滤.
      • where 是在分组前对数据进行过滤
      • having 后面可以使用分组函数(统计函数)
      • where 后面不可以使用分组函数。
  3. 图解:

  4. 练习:

    • 按照商品类别分组,统计各个分组商品的个数

      SELECT category_id,COUNT(*) FROM product GROUP BY category_id;
      
    • 按照商品类别分组,统计每组商品的平均价格

      SELECT category_id,AVG(price) FROM product GROUP BY category_id;
      
    • 按照商品类别分组,统计各个分组商品的个数,只查询每组商品价格大于200的商品

      where:用于分组前进行条件过滤
      having:用于分组后,对分组的数据进行条件过滤
      -- 先where过滤,在分组,在统计
      SELECT category_id,COUNT(*) FROM product WHERE price>200 GROUP BY category_id;
      
    • 按照商品类别分组,统计各个分组商品的个数,且只显示统计个数等于3的信息

      -- 先where过滤,在分组,在统计,在having过滤 
      SELECT category_id,COUNT(*) FROM product GROUP BY category_id HAVING COUNT(*)=3;
      

二.SQL备份与恢复

2.1 SQL备份

  1. 数据库的备份是指将数据库转换成对应的sql文件

2.1.1 MySQL命令备份

  1. 数据库导出sql脚本的格式:

    mysqldump -u用户名 -p密码 数据库名>生成的脚本文件路径
    
  2. 例如:

    mysqldump -uroot -proot sgw1>d:\sgw2.sql
    
  3. 以上备份数据库的命令中需要用户名和密码,即表明该命令要在用户没有登录的情况下使用

2.1.2 可视化工具备份

  1. 选中数据库,右键 ”备份/导出” , 指定导出路径,保存成.sql文件即可。
    mysql查询DQL&多表关系_第1张图片

2.2 SQL恢复

  1. 数据库的恢复指的是使用备份产生的sql文件恢复数据库,即将sql文件中的sql语句执行就可以恢复数据库内容。

2.2.1 MySQL命令恢复

  1. 使用数据库命令备份的时候只是备份了数据库内容,产生的sql文件中没有创建数据库的sql语句,在恢复数据库之前需要自己动手创建数据库。
    • 在数据库外恢复
      • 格式: mysql -uroot -p密码 数据库名 < 文件路径
      • 例如: mysql -uroot -proot sgw1
    • 在数据库内恢复
      • 格式: source SQL脚本路径
      • 例如: source d:\sgw1.sql
      • 注意:使用这种方式恢复数据,首先要登录数据库.

2.2.2 可视化工具恢复

  1. 数据库列表区域右键“从SQL转储文件导入数据库”, 指定要执行的SQL文件,执行即可。
    mysql查询DQL&多表关系_第2张图片

三.多表操作

  1. 实际开发中,一个项目通常需要很多张表才能完成。例如:一个商城项目就需要分类表 (category) 、商品表 (products) 、订单表 (orders) 等多张表。且这些表的数据之间存在一定的关系,接下来我们将在单表的基础上,一起学习多表方面的知识。

3.1 表与表之间的关系

  1. 一对多关系

    • 常见实例:客户和订单,分类和商品,部门和员工.

    • 一对多建表原则:在从表(多方)创建一个字段,字段作为外键指向主表(一方)的主键.
      mysql查询DQL&多表关系_第3张图片

  2. 多对多关系

    • 常见实例:学生和课程、用户和角色

    • 多对多关系建表原则:需要创建第三张表,中间表中至少两个字段,这两个字段分别作为外键指向各自一方的主键.
      mysql查询DQL&多表关系_第4张图片

  3. 一对一关系:(了解)

    • 在实际的开发中应用不多.因为一对一可以创建成一张表.
    • 两种建表原则:
      • 外键唯一:主表的主键和从表的外键(唯一),形成主外键关系,外键唯一unique。
      • 外键是主键:主表的主键和从表的主键,形成主外键关系。

3.2 外键约束

  1. 现在我们有两张表 “分类表”“商品表” ,为了表明商品属于哪个分类,通常情况下,我们将在商品表上添加一列,用于存放分类cid的信息,此列称为:外键
    mysql查询DQL&多表关系_第5张图片

  2. 此时 “分类表category” 称为:主表,“cid” 我们称为主键。“商品表products” 称为:从表,category_id 称为外键。我们通过主表的主键和从表的外键来描述主外键关系,呈现就是一对多关系。

    • 外键特点:

      • 从表外键的值是对主表主键的引用。
      • 从表外键类型,必须与主表主键类型一致。
      • 主表中有的数据,从表可以有,可以没有
      • 主表中没有的数据,从表中也不能有
      • 删除主表中的数据,必须保证从表没有使用
    • 声明外键约束

      语法:
      alter table 从表 add [constraint][外键名称] foreign key (从表外键字段名) references 主表 (主表的主
      键);
      [外键名称]用于删除外键约束的,一般建议“_fk”结尾
      alter table 从表 drop foreign key 外键名称
      
    • 使用外键目的:

      • 保证数据的准确性和完整性

3.3 一对多

  1. 建表原则:从表使用主表的主键作为外键
    • 主表:分类表 category
    • 从表:商品表 products

3.3.1 分析

mysql查询DQL&多表关系_第6张图片

  1. category分类表,为一方,也就是主表,必须提供主键cid
  2. products商品表,为多方,也就是从表,必须提供外键category_id

3.3.2 实现:分类和商品

  1. 创建分类表

    create table category(
    cid varchar(32) PRIMARY KEY ,
    cname varchar(100) -- 分类名称
    );
    
  2. 商品表

    CREATE TABLE `products` (
    `pid` varchar(32) PRIMARY KEY ,
    `name` VARCHAR(40) ,
    `price` DOUBLE
    );
    
  3. 添加外键字段

    alter table products add column category_id varchar(32);
    
  4. 添加约束

    alter table products add constraint product_fk foreign key (category_id) references category
    (cid);
    

3.3.3 操作

  1. 向分类表中添加数据

    INSERT INTO category (cid ,cname) VALUES('c001','服装');
    
  2. 向商品表添加普通数据,没有外键数据,默认为null

    INSERT INTO products (pid,pname) VALUES('p001','商品名称');
    
  3. 向商品表添加普通数据,含有外键信息(category表中存在这条数据)

    INSERT INTO products (pid ,pname ,category_id) VALUES('p002','商品名称2','c001');
    
  4. 向商品表添加普通数据,含有外键信息(category表中不存在这条数据) – 失败,异常

    INSERT INTO products (pid ,pname ,category_id) VALUES('p003','商品名称2','c999');
    
  5. 删除指定分类(分类商品使用) – 执行异常

    DELETE FROM category WHERE cid = 'c001';
    

3.4 多对多

  1. 建表原则:创建一张中间表,使用两个主表的主键作为外键
    • 主表: 商品表 products 订单表 orders
    • 中间表: products_orders

3.4.1 分析

mysql查询DQL&多表关系_第7张图片

  1. 商品和订单多对多关系,将拆分成两个一对多。
  2. products商品表,为其中一个一对多的主表,需要提供主键pid
  3. orders 订单表,为另一个一对多的主表,需要提供主键oid
  4. orderitem中间表,为另外添加的第三张表,需要提供两个外键oid和pid

3.4.2 实现:订单和商品

  1. 商品表

    CREATE TABLE `products` (
    `pid` varchar(32) PRIMARY KEY ,
    `name` VARCHAR(40) ,
    `price` DOUBLE
    );
    
  2. 订单表

    create table `orders`(
    `oid` varchar(32) PRIMARY KEY ,
    `totalprice` double #总计
    );
    
  3. 订单项表

    create table orderitem(
    oid varchar(50),-- 订单id
    pid varchar(50)-- 商品id
    );
    
  4. 订单表和订单项表的主外键关系

    alter table `orderitem` add constraint orderitem_orders_fk foreign key (oid) references
    orders(oid);
    
  5. 商品表和订单项表的主外键关系

    alter table `orderitem` add constraint orderitem_product_fk foreign key (pid) references
    products(pid);
    
  6. 联合主键(可省略)

    alter table `orderitem` add primary key (oid,pid);
    

3.4.3 操作

  1. 向商品表中添加数据

    INSERT INTO products (pid,pname) VALUES('p003','商品名称');
    
  2. 向订单表中添加数据

    INSERT INTO orders (oid ,totalprice) VALUES('x001','998');
    INSERT INTO orders (oid ,totalprice) VALUES('x002','100');
    
  3. 向中间表添加数据(数据存在)

    INSERT INTO orderitem(pid,oid) VALUES('p001','x001');
    INSERT INTO orderitem(pid,oid) VALUES('p001','x002');
    INSERT INTO orderitem(pid,oid) VALUES('p002','x002');
    
  4. 删除中间表的数据

    DELETE FROM orderitem WHERE pid='p002' AND oid = 'x002';
    
  5. 向中间表添加数据(数据不存在) – 执行异常

    INSERT INTO orderitem(pid,oid) VALUES('p002','x003');
    
  6. 删除商品表的数据 – 执行异常

    DELETE FROM products WHERE pid = 'p001';
    

3.5 一对一(了解)

  1. 建表原则:1张表使用另外一张表的主键作为外键(主键)

  2. 图解:
    mysql查询DQL&多表关系_第8张图片

3.6 自关联1对多关系(了解)

  1. 建表原则:本表的外键使用本表的主键

  2. 创建地区表:area 字段:地区主键,地区名称,地区描述,所属省份

    • 建地区表:

      CREATE TABLE AREA(
      	-- 地区主键
      	aid INT PRIMARY KEY AUTO_INCREMENT,
      	-- 地区名称
      	aname VARCHAR(20),
      	-- 地区描述
      	description VARCHAR(50),
      	-- 所属省份(外键)
      	area_aid INT,
      	-- 添加area_aid字段的外键约束
      	FOREIGN KEY(area_aid) REFERENCES AREA(aid)
      );
      
    • 添加数据的时候,如果没有写外键字段,默认使用NULL值

      INSERT INTO AREA(aname,description) VALUES('河北','雾霾'),('内蒙古','草原'),('广东','经济特区');
      INSERT INTO AREA(aname,description,area_aid) VALUES('石家庄','雾霾之最',1),('承德','避暑山庄',1);
      INSERT INTO AREA(aname,description,area_aid) VALUES('包头','草原钢城',2),('赤峰','红山文化',2);
      INSERT INTO AREA(aname,description,area_aid) VALUES('深圳','经济特区',3),('东莞','服务行业',3);
      
    • 弊端,添加不存在省份的数据

      INSERT INTO AREA(aname,description,area_aid) VALUES('香港','旅游购物',4);
      

四:扩展(分页查询)

  1. 使用关键字:limit

    • 格式:

      • 只要前n条数据

        select *|字段 from 表名 limit n;
        
      • 分页查询

        select *|字段 from 表名 limit m,n;
        -- m:每页开始行的索引,变化的
        -- n:每页显示的数量,不变的
        
  2. 注意:数据库行的索引从0开始,列的索引从1开始

  3. 图解:

  4. 代码实例:

    • 只要前6条数据

      SELECT * FROM product LIMIT 6;
      
    • 分页查询,每页显示5条,查询第1页

      SELECT * FROM product LIMIT 0,5;
      
    • 分页查询,每页显示5条,查询第2页

      SELECT * FROM product LIMIT 5,5;
      
    • 分页查询,每页显示5条,查询第3页

      SELECT * FROM product LIMIT 10,5;
      

你可能感兴趣的:(MySQL)