1. 程式人生 > >人工智慧(mysql)—— mysql高階查詢(索引、多表、連線)

人工智慧(mysql)—— mysql高階查詢(索引、多表、連線)

一、索引

    1、索引的定義

                對資料庫中表的一列或者多列的值進行排序的一種結構(MySQL中索引用Btree方式)

    2、索引的優點

                加快資料的檢索速度

    3、索引的缺點

                a、需動態維護,佔用系統資源,降低資料維護速度
                b、佔用物理儲存空間

    4、索引對比

            a、執行 insert.py 檔案(參見附錄1),插入100萬條記錄(終端視窗)
                    python3 insert.py
            b、開啟效能分析(mysql環境)
                    set profiling=1;
                            備註 :show variables like "profiling";
            c、執行查詢語句
                    select name from t1 where name="lucy99999";
            d、檢視效能分析結果
                    show profiles;
            e、給name欄位建立索引
                    create index name on t1(name);
            f、執行查詢語句
                    select name from t1 where name="lucy88888";
            g、檢視效能分析結果
                    show profiles;
            h、關閉效能分析
                    set profiling = 0;

    5、索引型別

            普通索引(index),唯一索引(unique),主鍵索引(primary key)&&自增長屬性(auto_increment),外來鍵(foreign key)

二、索引型別

    1、普通索引(index)

            a、使用規則

                    1)一個表中可以有多個index欄位
                    2)欄位的值可以重複,也可以為NULL
                    3)經常把做查詢條件的欄位設定為index欄位
                    4)index欄位的key標誌位:MUL


            b、建立
                    1)建立表時建立index
                             語法:index(欄位名),
create  table  t4(
id  int,
name  varchar(20),
index(id),
index(name)
);
desc  t4;

                    2)在已有表中新增索引欄位
                             語法:create  index  索引名  on  表名(欄位名);
                                    # 索引名一般和欄位名一樣,也可以自己定義索引名


alter  table  t4  add  score  tinyint;
create  index  score  on  t4(score);
desc t4;
            c、檢視普通索引

                    1)desc  表名;     --> 檢視KEY標誌位MUL
                    2)show  index  from  表名\G;

show  index  from  t4;
show  index  from  t4\G;
            d、刪除

                    drop index 索引名 on 表名;
                            注意:刪除普通索引只能一個一個刪除

drop index name on t4;
drop index score on t3; 

    2、唯一索引(unique)

            a、使用規則
                    1)一個表中可以有多個unique欄位
                    2)unique欄位的值不允許重複,可以為空值NULL
                    3)unique的KEY表中是UNI
            b、建立(基本等同index建立)
                    1)建立表
                            unique(欄位名),
create  table  t5(
id  int,
name  varchar(20),
unique(id),
unique(name)
);
                    2)已有表
                            create unique index 索引名 on 表名(欄位名);
                                    # 索引名一般和欄位名一樣,也可以自己定義索引名
alter table t5 add name varchar(10);
create unique  index  name_index on t5(name);
            c、檢視、刪除同普通索引
                    desc  表名;
                    show  index  from  表名;
                    drop  index  索引名  on  表名;
                            注:
                                Non_unique: 0 --> 唯一索引
                                Non_unique: 1 --> 普通索引

    3、主鍵索引(primary key)&&自增長屬性(auto_increment)

            a、使用規則

                    1)一個表中只能有一個主鍵欄位
                    2)對應欄位的值不允許重複  且  不能為空值NULL
                    3)主鍵欄位的KEY標誌位:PRI
                    4)把表中能夠唯一標識一條記錄的欄位設定為主鍵,通常把表中記錄編號id的欄位設定為主鍵

            b、建立主鍵(PRI)

                    1)建立表時
                            格式1:欄位名  資料型別  primary  key  auto_increment,

create table t6(
id int primary key auto_increment,
name varchar(10)
);

                            格式2:primary  key(id),

create table t7(
id int  auto_increment,
name varchar(10),
primary key(id)
);

                    2)已有表
                            I、在已有表中新增主鍵
                                    alter  table  表名  add  primary key(欄位名) ;
                            II、在已有表中新增自增長屬性
                                    alter  table  表名  modify  欄位名  資料型別  auto_increment;
                                                注:欄位名的資料型別可以重新指定

create table t8(
id int,
name varchar(10)
);
alter  table  t8  add  primary key(id);
alter  table  t8  modify  id  bigint  auto_increment;
            c、刪除主鍵

                    1)刪除自增長屬性
                            alter table 表名 modify id 資料型別;
                    2)刪除主鍵
                            alter table 表名 drop primary key;

            d、指定自增長屬性起始值

                    1)建立表(建立時就指定起始值)
                            create table 表名(
                            id int primary key auto_increment,
                            ... ...
                            )auto_increment=10000;
                    2)已有表(自增長屬性必須已存在,才能新增起始值
                            alter table 表名 auto_increment=10000;

alter table t8 auto_increment=1000;

    4、外來鍵(foreign key)

            a、定義
                    讓當前表字段值從另一個表範圍內選擇
            b、語法格式
                    foreign key(參考欄位名)
                    references 主表(被參考欄位名)
                    on delete 級聯動作
                    on update 級聯動作
            c、使用規則
                    1)兩張表被參考欄位(主表)和參考欄位(從表)資料型別要一致
                    2)主表被參考欄位 :主鍵
            d、級聯動作
                    1)cascade 資料級聯更新
                            當主表刪除級聯時,從表會級聯更新
                            當主表更新被參考欄位的值時,從表會級聯更新
                    2)restrict 預設
                            當刪除主表記錄時,如果從表中有相管理記錄則不允許主表刪除
                            更新同理
                    3)set  null
                            當主表刪除記錄時,從表中相關聯記錄的參考欄位值自動設定為NULL
                            更新同理
                   4)no  action
                            on delete no action on update no action
                            同 restrict,都是立即檢查外來鍵限制   
            e、示例
表1、繳費資訊表(財務)
學號姓名班級金額
1唐伯虎AID110
2點秋香AID18
表2、學生資訊表(班主任)
學號姓名金額
1唐伯虎10
2點秋香8
                    建立主表、從表
#主表:jftab
create table jftab(
id int primary key,
name varchar(20),
class char(7),
money int
)character set utf8;
insert into jftab values
(1,"唐伯虎","AID1",10),
(2,"點秋香","AID1",8);
#從表:bjtab
create table bjtab(
stu_id int,
name varchar(20),
money int,
foreign key(stu_id) references jftab(id)
on delete cascade
on update cascade)character set utf8;
insert into bjtab values
(1,"唐伯虎",10),
(2,"點秋香",8);
            g、刪除外來鍵
                    alter  table  表名 drop  foreign  key  外來鍵名;
                            注:
                                    外來鍵名的檢視方式:show  create  table 表名;

            h、在已有表中新增外來鍵
                    ## 會受到表中原有資料的限制
                    alter  table  表名 add  foreign  key(參考欄位名)
                    references  主表(被參考欄位名)
                    on  delete  級聯動作
                    on  update  級聯動作;

二、多表查詢

    1、select 欄位名列表 from 表1,表2;

                相當於笛卡爾積(不加where)
                表1中所有欄位分別和表2的第一個欄位匹配,然後表1中所有欄位分別和表2的下一個欄位匹配,...

    2、select 欄位名列表 from 表1,表2 where 條件;

                等同於連線查詢中的內連線(inner join)

# 通過附錄2建立表,然後查詢
a、顯示 省、市詳細資訊
select sheng.s_name,city.c_name from sheng,city
where sheng.s_id=city.cfather_id;
b、顯示 省、市、縣詳細資訊
select sheng.s_name,city.c_name,xian.x_name from sheng,city,xian
where sheng.s_id=city.cfather_id and city.c_id=xian.xfather_id;

三、連線查詢

    1、內連線

            從表中刪除與其他被連線的表中沒有匹配到的行(只顯示匹配到的行)

            語法格式
                    select  欄位名列表  from  表1
                    inner  join  表2  on  條件  
                    inner  join  表3  on  條件;

1、顯示 省、市詳細資訊
select sheng.s_name,city.c_name from sheng 
inner join city on sheng.s_id=city.cfather_id;
2、顯示 省、市、縣詳細資訊
select sheng.s_name,city.c_name,xian.x_name from sheng
inner join city on sheng.s_id=city.cfather_id
inner join xian on city.c_id=xian.xfather_id;

    2、外連線

        a、左連線

                以左表為主顯示查詢結果

                語法格式
                        select  欄位名列表  from  表1
                        left  join  表2  on  條件;
a.以省表為主(省全部顯示),顯示省、市詳細資訊
select sheng.s_name,city.c_name from sheng 
left join city on sheng.s_id=city.cfather_id;           
b.以縣表為主(縣全部顯示),顯示省、市、區詳細資訊
select sheng.s_name,city.c_name,xian.x_name from sheng 
left join city on sheng.s_id=city.cfather_id 
left join xian on city.c_id=xian.xfather_id;
c.以市表為主(市全部顯示),顯示省、市、區詳細資訊
select sheng.s_name,city.c_name,xian.x_name from sheng 
right join city on sheng.s_id=city.cfather_id 
left join xian on city.c_id=xian.xfather_id;
        b、右連線
                用法同左連線,以右表為主顯示查詢結果

四、附錄1:insert.py 檔案

import pymysql

db = pymysql.connect("localhost","root","123456")
cursor = db.cursor()
cursor.execute("create database indexdb;")
cursor.execute("use indexdb;")
cursor.execute("create table t1(id int,name char(20));")
n = 1
name="lucy"
while n <= 2000000:
    cursor.execute("insert into t1 values('%s','%s')" % (n,name+str(n)))
    # n = int(n)
    n += 1

db.commit()
cursor.close()
db.close()

五、附錄2:建立省、市、區表

create table sheng(
id int primary key auto_increment,
s_id int,
s_name varchar(15)
)default charset=utf8;

insert into sheng values
(1, 130000, '河北省'),
(2, 140000, '陝西省'),
(3, 150000, '四川省'),
(4, 160000, '廣東省'),
(5, 170000, '山東省'),
(6, 180000, '湖北省'),
(7, 190000, '河南省'),
(8, 200000, '海南省'),
(9, 200001, '雲南省'),
(10,200002,'山西省');


create table city(
id int primary key auto_increment,
c_id int,
c_name varchar(15),
cfather_id int
)default charset=utf8;

insert into city values
(1, 131100, '石家莊市', 130000),
(2, 131101, '滄州市', 130000),
(3, 131102, '廊坊市', 130000),
(4, 131103, '西安市', 140000),
(5, 131104, '成都市', 150000),
(6, 131105, '重慶市', 150000),
(7, 131106, '廣州市', 160000),
(8, 131107, '濟南市', 170000),
(9, 131108, '武漢市', 180000),
(10,131109, '鄭州市', 190000),
(11,131110, '北京市', 320000),
(12,131111, '天津市', 320000),
(13,131112, '上海市', 320000),
(14,131113, '哈爾濱', 320001),
(15,131114, '雄安新區', 320002);


create table xian(
id int primary key auto_increment,
x_id int,
x_name varchar(15),
xfather_id int
)default charset=utf8;

insert into xian values
(1, 132100, '正定縣', 131100),
(2, 132102, '浦東新區', 131112),
(3, 132103, '武昌區', 131108),
(4, 132104, '哈哈', 131115),
(5, 132105, '安新縣', 131114),
(6, 132106, '容城縣', 131114),
(7, 132107, '雄縣', 131114),
(8, 132108, '嘎嘎', 131115);

六:附錄3:目錄

七、練習

綜述:兩張表,一張顧客資訊表customers,一張訂單表orders
1、建立一張顧客資訊表customers,欄位要求如下:
    c_id 型別為整型,設定為主鍵,並設定為自增長屬性
    c_name 字元型別,變長,寬度為20
    c_age 微小整型,取值範圍為0~255(無符號)
    c_sex 列舉型別,要求只能在('M','F')中選擇一個值
    c_city 字元型別,變長,寬度為20
    c_salary 浮點型別,要求整數部分最大為10位,小數部分為2位
    在表中任意插入3條記錄,c_name為"Zhangsan","Lisi","Wangwu", c_city儘量    寫"Beijing","Shanghai" ......
2、建立一張訂單表orders,欄位要求如下:
    o_id 整型
    o_name 字元型別,變長,寬度為30
    o_price 浮點型別,整數最大為10位,小數部分為2位
    設定此表中的o_id欄位為customers表中c_id欄位的外來鍵,更新刪除同步
    在表中任意插入5條記錄(注意外來鍵限制)
    o_name分別為"iphone","ipad","iwatch","mate9","r11",其他資訊自己定
3、返回customers表中,工資大於4000元,或者年齡小於29歲,滿足這樣條件的前2條記錄    
4、把customers表中,年齡大於等於25歲,並且地址是北京或者上海,這樣的人的工資上調15%
5、把customers表中,城市為北京的顧客,按照工資降序排列,並且只返回結果中的第一條記錄        
6、選擇工資salary最少的顧客的資訊    
7、找到工資大於5000的顧客都買過哪些產品的記錄明細
8、刪除外來鍵限制    

9、刪除customers主鍵限制

以下是整個操作的過程(使用者名稱:root,密碼:123456),根據自己的使用者名稱、密碼登入。

        注:進入mysql互動終端$  mysql -uroot -p123456

mysql> create database homework
    -> ;
Query OK, 1 row affected (0.13 sec)

mysql> use homework;
Database changed
mysql> 

mysql> create table customers(
    -> c_id int primary key auto_increment,
    -> c_name varchar(20),
    -> c_age tinyint unsigned,
    -> c_sex enum("M","F"),
    -> c_city varchar(20),
    -> c_salary double(12,2));
Query OK, 0 rows affected (0.54 sec)

mysql> desc customers;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| c_id      | int(11)             | NO   | PRI | NULL    | auto_increment |
| c_name    | varchar(20)         | YES  |     | NULL    |                |
| c_age     | tinyint(3) unsigned | YES  |     | NULL    |                |
| c_sex     | enum('M','F')       | YES  |     | NULL    |                |
| c_city    | varchar(20)         | YES  |     | NULL    |                |
| c_salary | double(12,2)        | YES  |     | NULL    |                |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.05 sec)


mysql> insert into customers values(1,"Zhangsan",20,"M","Shenzhen",2345.23);
Query OK, 1 row affected (0.21 sec)

mysql> insert into customers values(2,"Lisi",23,"F","Shanghai",7345.23);
Query OK, 1 row affected (0.02 sec)

mysql> insert into customers values(3,"Wangwu",29,"M","Beijing",70345.23);
Query OK, 1 row affected (0.01 sec)

mysql> create table orders(
    -> o_id int,
    -> o_name varchar(30),
    -> o_price double(12,2),
    -> foreign key(o_id)
    -> references customers(c_id)
    -> on delete cascade
    -> on update cascade);
Query OK, 0 rows affected (0.12 sec)

mysql> desc orders;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| o_id    | int(11)      | YES  | MUL | NULL    |       |
| o_name  | varchar(30)  | YES  |     | NULL    |       |
| o_price | double(12,2) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
3 rows in set (0.02 sec)

mysql> insert into orders values(1,"iphone",293.1);
Query OK, 1 row affected (0.03 sec)

mysql> insert into orders values(3,"ipad",493.1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into orders values(3,"iwatch",334.1);
Query OK, 1 row affected (0.02 sec)

mysql> insert into orders values(2,"mate9",199.9);
Query OK, 1 row affected (0.02 sec)

mysql> insert into orders values(1,"r11",99.9);
Query OK, 1 row affected (0.01 sec)

mysql> select * from orders;
+------+--------+---------+
| o_id | o_name | o_price |
+------+--------+---------+
|    1 | iphone |  293.10 |
|    3 | ipad   |  493.10 |
|    3 | iwatch |  334.10 |
|    2 | mate9  |  199.90 |
|    1 | r11    |   99.90 |
+------+--------+---------+
5 rows in set (0.00 sec)

mysql> desc customers;
+-----------+---------------------+------+-----+---------+----------------+
| Field     | Type                | Null | Key | Default | Extra          |
+-----------+---------------------+------+-----+---------+----------------+
| c_id      | int(11)             | NO   | PRI | NULL    | auto_increment |
| c_name    | varchar(20)         | YES  |     | NULL    |                |
| c_age     | tinyint(3) unsigned | YES  |     | NULL    |                |
| c_sex     | enum('M','F')       | YES  |     | NULL    |                |
| c_city    | varchar(20)         | YES  |     | NULL    |                |
| c_salary | double(12,2)        | YES  |     | NULL    |                |
+-----------+---------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

mysql> select * from customers where c_salary>4000 or c_age<29;
+------+----------+-------+-------+----------+----------+
| c_id | c_name   | c_age | c_sex | c_city   | c_salary |
+------+----------+-------+-------+----------+----------+
|    1 | Zhangsan |    20 | M     | Shenzhen |  2345.23 |
|    2 | Lisi     |    23 | F     | Shanghai |  7345.23 |
|    3 | Wangwu   |    29 | M     | Beijing  | 70345.23 |
+------+----------+-------+-------+----------+----------+
3 rows in set (0.00 sec)

mysql> update customers set c_salary=c_salary*1.15 where c_age>=25 and c_city in (
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from customers;
+------+----------+-------+-------+----------+----------+
| c_id | c_name   | c_age | c_sex | c_city   | c_salary |
+------+----------+-------+-------+----------+----------+
|    1 | Zhangsan |    20 | M     | Shenzhen |  2345.23 |
|    2 | Lisi     |    23 | F     | Shanghai |  7345.23 |
|    3 | Wangwu   |    29 | M     | Beijing  | 80897.01 |
+------+----------+-------+-------+----------+----------+
3 rows in set (0.00 sec)

mysql> select * from customers where c_city="Beijing" order by c_salary desc limit 1;
+------+--------+-------+-------+---------+----------+
| c_id | c_name | c_age | c_sex | c_city  | c_salary |
+------+--------+-------+-------+---------+----------+
|    3 | Wangwu |    29 | M     | Beijing | 80897.01 |
+------+--------+-------+-------+---------+----------+
1 row in set (0.03 sec)

mysql> select * from customers order by c_salary asc limit 1;
+------+----------+-------+-------+----------+----------+
| c_id | c_name   | c_age | c_sex | c_city   | c_salary |
+------+----------+-------+-------+----------+----------+
|    1 | Zhangsan |    20 | M     | Shenzhen |  2345.23 |
+------+----------+-------+-------+----------+----------+
1 row in set (0.00 sec)

mysql> select * from orders where o_id in (select c_id from customers where c_salary>5000);
+------+--------+---------+
| o_id | o_name | o_price |
+------+--------+---------+
|    2 | mate9  |  199.90 |
|    3 | ipad   |  493.10 |
|    3 | iwatch |  334.10 |
+------+--------+---------+
3 rows in set (0.02 sec)

mysql> show create table orders;
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                                                                                                                                                                                                         |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| orders | CREATE TABLE `orders` (
  `o_id` int(11) DEFAULT NULL,
  `o_name` varchar(30) DEFAULT NULL,
  `o_price` double(12,2) DEFAULT NULL,
  KEY `o_id` (`o_id`),
  CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`o_id`) REFERENCES `customers` (`c_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

mysql> alter table orders drop foreign key orders_ibfk_1;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table customers modify c_id int;
Query OK, 3 rows affected (0.16 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> alter table customers drop primary key ;
Query OK, 3 rows affected (0.12 sec)
Records: 3  Duplicates: 0  Warnings: 0