1. 程式人生 > >07-MYSQL多表查詢

07-MYSQL多表查詢

 今日任務

 完成對MYSQL資料庫的多表查詢及建表的操作



 教學目標

 掌握MYSQL中多表的建立及多表的查詢

 掌握MYSQL中的表關係分析並能正確建表



昨天內容回顧:

​    資料庫的建立 : create database 資料庫的名 character set 字符集  collate 校對規則

​    資料庫的刪除: drop database 資料庫名

​    修改: alter database 資料庫 character set 字符集(utf8)

​    查詢:  show databases;

​          show create database 資料庫的名字

​          select database();

​    切換資料庫 :

​            use 資料庫的名字

​    

​    表結構的操作:

​        建立:  create table 表名(    

​                列名 列的型別  列的約束,

​                列名 列的型別  列的約

​            )

​            列的型別: char / varchar   

​            列的約束: 

​                    primary key 主鍵約束

​                    unique : 唯一約束

​                    not null 非空約束

​              自動增長 : auto_increment

​         刪除 :  drop table 表名

​        修改:   alter table 表名 (add, modify, change , drop)

​            rename table 舊錶名  to 新表名

​            alter table 表名 character set 字符集

​       查詢表結構:

​            show tables; 查詢出所有的表

​            show create table 表名: 表的建立語句, 表的定義

​            desc 表名: 表的結構



​    表中資料的操作

​        插入:  insert into 表名(列名,列名) values(值1,值2);

​        刪除:        delete from 表名 [where 條件]

​        修改:        update 表名 set 列名='值' ,列名='值' [where 條件];

​        查詢:    select [distinct]  * [列名1,列名2] from 表名 [where 條件]

​              as關鍵字: 別名

​               where條件後面:

​        

​                    關係運算符:  > >= < <= !=  <>

​                        --判斷某一列是否為空:  is null    is not null

​                        in 在某範圍內

​                        between...and

​                    邏輯運算子: and or not

​                    模糊查詢:  like    

​                            _ : 代表單個字元

​                            %: 代表的是多個字元

​                    分組: group by 

​                    分組之後條件過濾:  having

​                    聚合函式: sum()  ,avg() , count()  ,max(), min()

​                    排序: order by  (asc 升序, desc 降序)


 SQL 會建立多表及多表的關係

 需求:

分類表和商品表之間是不是有關係? 如果有關係,在資料庫中如何表示這種關係

```sql
create table category(
  cid int primary key auto_increment,
  cname varchar(10),
  cdesc varchar(31)
);

insert into category values(null,'手機數碼','電子產品,黑馬生產');
insert into category values(null,'鞋靴箱包','江南皮鞋廠傾情打造');
insert into category values(null,'香菸酒水','黃鶴樓,茅臺,二鍋頭');
insert into category values(null,'酸奶餅乾','娃哈哈,蒙牛酸酸乳');
insert into category values(null,'饞嘴零食','瓜子花生,八寶粥,辣條');

select * from category;
select cname,cdesc from category;

--所有商品
1.商品ID
2.商品名稱
3.商品的價格
4.生產日期
5.商品分類ID

商品和商品分類 : 所屬關係
create table product(
    pid int primary key auto_increment,
      pname varchar(10),
      price double,
      pdate timestamp,
      cno int
);

insert into product values(null,'小米mix4',998,null,1);
insert into product values(null,'錘子',2888,null,1);
insert into product values(null,'阿迪王',99,null,2);
insert into product values(null,'老村長',88,null,3);
insert into product values(null,'勁酒',35,null,3);
insert into product values(null,'小熊餅乾',1,null,4);
insert into product values(null,'衛龍辣條',1,null,5);
insert into product values(null,'旺旺大餅',1,null,5);

//插入資料會失敗
insert into product values(null,'充氣的',1,null,12);

```



 技術分析:

- 多表之間的關係如何來維護

  外來鍵約束: foreign key

  - 給product中的這個cno 新增一個外來鍵約束

    alter table product add foreign key(cno)  references  category(cid);

  - 自己挖坑

  - 從分類表中,刪除分類為5資訊,

    - delete from category where cid =5;  //刪除失敗
    - 首先得去product表, 刪除所有分類ID5  商品

- 建資料庫原則:

  - 通常情況下,一個專案/應用建一個數據庫


- 多表之間的建表原則

  - 一對多 : 商品和分類

    - 建表原則: 在多的一方新增一個外來鍵,指向一的一方的主鍵

      ​

  - 多對多: 老師和學生, 學生和課程

    建表原則: 建立一張中間表,將多對多的關係,拆分成一對多的關係,中間表至少要有兩個外來鍵,分別指向原來的那兩張表

    ​

  - 一對一: 班級和班長, 公民和身份證, 國家和國旗

    - 建表原則:  

      - 將一對一的情況,當作是一對多情況處理,在任意一張表新增一個外來鍵,並且這個外來鍵要唯一,指向另外一張表
      - 直接將兩張表合併成一張表
      - 將兩張表的主鍵建立起連線,讓兩張表裡面主鍵相等

    - 實際用途: 用的不是很多.    (拆表操作  )

      - 相親網站: 
        - 個人資訊 : 姓名,性別,年齡,身高,體重,三圍,興趣愛好,(年收入,  特長,學歷, 職業, 擇偶目標,要求)
        - 拆表操作 : 將個人的常用資訊和不常用資訊,減少表的臃腫, 

      ​









 

- 網上商城表例項的分析:  使用者購物流程

  ​


- 使用者表 (使用者的ID,使用者名稱,密碼,手機)

  ```sql
  create table user(
      uid int primary key auto_increment,
        username varchar(31),
        password varchar(31),
        phone  varchar(11)
  );

  insert into user values(1,'zhangsan','123','13811118888');
  ```

- 訂單表 (訂單編號,總價,訂單時間 ,地址,外來鍵使用者的ID)

  ```sql
    create table orders(
        oid int primary key auto_increment,
          sum int not null,
        otime timestamp,
          address varchar(100),
          uno int,
          foreign key(uno) references user(uid)
    );
    insert into orders values(1,200,null,'黑馬前臺旁邊小黑屋',1);
    insert into orders values(2,250,null,'黑馬後臺旁邊1702',1);
  ```



-   商品表 (商品ID, 商品名稱,商品價格,外來鍵cno)

    ```sql
    create table product(
        pid int primary key auto_increment,
          pname varchar(10),
          price double,
          cno int,
          foreign key(cno) references category(cid)
    );

    insert into product values(null,'小米mix4',998,1);
    insert into product values(null,'錘子',2888,1);
    insert into product values(null,'阿迪王',99,2);
    insert into product values(null,'老村長',88,3);
    insert into product values(null,'勁酒',35,3);
    insert into product values(null,'小熊餅乾',1,4);
    insert into product values(null,'衛龍辣條',1,5);
    insert into product values(null,'旺旺大餅',1,5);
    ```

    ​



- 訂單項: 中間表(訂單ID,商品ID,商品數量,訂單項總價)

  ```sql
  create table orderitem(
      ono int,
        pno int,
        foreign key(ono) references orders(oid),
        foreign key(pno) references product(pid),
        ocount int,
        subsum double
  );
  --給1號訂單新增商品 200塊錢的商品
  insert into orderitem values(1,7,100,100);
  insert into orderitem values(1,8,101,100);

  --給2號訂單新增商品 250塊錢的商品 ()
  insert into orderitem values(2,5,1,35);
  insert into orderitem values(2,3,3,99);
  ```

  ​

  ​



-   商品分類表(分類ID,分類名稱,分類描述)

    ```sql
    create table category(
        cid int primary key auto_increment,
          cname varchar(15),
          cdesc varchar(100)
    );

    insert into category values(null,'手機數碼','電子產品,黑馬生產');
    insert into category values(null,'鞋靴箱包','江南皮鞋廠傾情打造');
    insert into category values(null,'香菸酒水','黃鶴樓,茅臺,二鍋頭');
    insert into category values(null,'酸奶餅乾','娃哈哈,蒙牛酸酸乳');
    insert into category values(null,'饞嘴零食','瓜子花生,八寶粥,辣條');
    ```






- 多表之間的關係如何維護: 外來鍵約束 :   foreign key
- 新增一個外來鍵: alter table product add foreign key(cno)  references category(cid);
  - ​        foreign key(cno) references category(cid)
  - 刪除的時候, 先刪除外來鍵關聯的所有資料,再才能刪除分類的資料
- 建表原則:
  - 一對多:
    - 建表原則: 在多的一方增加一個外來鍵,指向一的一方
  - 多對多:
    - 建表原則: 將多對多轉成一對多的關係,建立一張中間表
  - 一對一: 不常用, 拆表操作
    - 建表原則:  將兩張表合併成一張表
      - 將兩張表的主鍵建立起關係
      - 將一對一的關係當作一對多的關係去處理




主鍵約束: 預設就是不能為空, 唯一

-  外來鍵都是指向另外一張表的主鍵
-  主鍵一張表只能有一個

唯一約束:  列面的內容, 必須是唯一, 不能出現重複情況, 為空

- 唯一約束不可以作為其它表的外來鍵
- 可以有多個唯一約束



一對多 : 建表原則: 在多的一方新增一個外來鍵,指向一的一方

多對多: 建表原則:

​        拆成一對多

​        建立一張中間表, 至少要有兩個外來鍵, 指向原來的表

一對一: 建表原則: 合併一張表, 將主鍵建立關係 , 將它當作一對多的情況來處理





- 資料庫客戶端軟體

  ​



 使用商城表完成對商品資訊的多表查詢

 需求分析:

在我們的商城案例中,我的訂單中包含很多資訊.開啟我的訂單需要去查詢表

 技術分析:

 多表查詢

- 交叉連線查詢  笛卡爾積



- 內連線查詢



- 左外連線



- 右外連線  


 分頁查詢

- 每頁資料資料3

- 起始索引從0 

- 第1頁: 0

- 第2頁: 3

  起始索引:  index 代表顯示第幾頁 頁數從1開始

  每頁顯示3條資料

  startIndex  = (index-1)*3

  ​

第一個引數是索引 

第二個引數顯示的個數

select * from product limit 0,3;

select * from product limit 3,3;



 子查詢(瞭解的內容,非常重要)

查詢出(商品名稱,商品分類名稱)資訊

```sql

```

  查詢分類名稱為手機數碼的所有商品

```sql
select * from product where cname ='手機數碼';

```

 練習題

- 按照商品分類的名稱統計商品的個數:

```sql
 
```

- 查詢1號訂單的訂單項資訊和商品資訊

```sql

```


 多表查詢練習資料

- 員工資訊表

```sql
--員工資訊表
CREATE TABLE emp(
    empno INT,
    ename VARCHAR(50),
    job VARCHAR(50),
    mgr    INT,
    hiredate DATE,
    sal    DECIMAL(7,2),
    comm DECIMAL(7,2),
    deptno INT
) ;

INSERT INTO emp values(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO emp values(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO emp values(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO emp values(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO emp values(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO emp values(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO emp values(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO emp values(7788,'SCOTT','ANALYST',7566,'1987-04-19',3000,NULL,20);
INSERT INTO emp values(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO emp values(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO emp values(7876,'ADAMS','CLERK',7788,'1987-05-23',1100,NULL,20);
INSERT INTO emp values(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO emp values(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO emp values(7934,'MILLER','CLERK',7782,'1982-01-23',1300,NULL,10);
INSERT INTO emp values(7981,'MILLER','CLERK',7788,'1992-01-23',2600,500,20);
```

- 部門資訊表

```sql
CREATE TABLE dept(
    deptno        INT,
    dname        varchar(14),
    loc        varchar(13)
);

INSERT INTO dept values(10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO dept values(20, 'RESEARCH', 'DALLAS');
INSERT INTO dept values(30, 'SALES', 'CHICAGO');
INSERT INTO dept values(40, 'OPERATIONS', 'BOSTON');
```

- 基本查詢

```sql
--所有員工的資訊
--薪資大於等於1000並且小於等於2000的員工資訊
--從員工表中查詢出所有的部門編號
--查詢出名字以A開頭的員工的資訊
--查詢出名字第二個字母是L的員工資訊
--查詢出沒有獎金的員工資訊
--所有員工的平均工資
--所有員工的工資總和
--所有員工的數量
--最高工資
--最少工資
--最高工資的員工資訊
--最低工資的員工資訊
```

- 分組查詢

```sql
--每個部門的平均工資
```

- 子查詢

```sql
-- 單行子查詢(> < >= <= = <>)
    -- 查詢出高於10號部門的平均工資的員工資訊
    
-- 多行子查詢(in  not in any all)    >any  >all
    -- 查詢出比10號部門任何員工薪資高的員工資訊

-- 多列子查詢(實際使用較少)   in
    -- 和10號部門同名同工作的員工資訊
-- Select接子查詢
    -- 獲取員工的名字和部門的名字
-- from後面接子查詢
    -- 查詢emp表中經理資訊
-- where 接子查詢
    -- 薪資高於10號部門平均工資的所有員工資訊
-- having後面接子查詢
    -- 有哪些部門的平均工資高於30號部門的平均工資

-- 工資>JONES工資
-- 查詢與SCOTT同一個部門的員工
-- 工資高於30號部門所有人的員工資訊
-- 查詢工作和工資與MARTIN完全相同的員工資訊
-- 有兩個以上直接下屬的員工資訊
-- 查詢員工編號為7788的員工名稱,員工工資,部門名稱,部門地址
```

- SQL查詢的綜合案例
1. 查詢出高於本部門平均工資的員工資訊


2. 列出達拉斯加工作的人中,比紐約平均工資高的人
3. 查詢7369員工編號,姓名,經理編號和經理姓名
4. 查詢出各個部門薪水最高的員工所有資訊


 面試題

```sql
CREATE TABLE test(
  name CHAR(20),
  kecheng CHAR(20),
  fenshu CHAR(20)
);

INSERT INTO test VALUES('張三','語文',81),
('張三','數學',75),
('李四','語文',76),
('李四','數學',90),
('王五','語文',81),
('王五','數學',82);

--請用一條Sql語句查處分數大於80的學生
```