1. 程式人生 > >MariaDB 連接查詢與子查詢(6)

MariaDB 連接查詢與子查詢(6)

sts query 判斷 affect 嵌套 all wid 實驗 des

MariaDB數據庫管理系統是MySQL的一個分支,主要由開源社區在維護,采用GPL授權許可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由於現在閉源了,而能輕松成為MySQL的代替品.在存儲引擎方面,使用XtraDB來代替MySQL的InnoDB,MariaDB由MySQL的創始人Michael Widenius主導開發,他早前曾以10億美元的價格,將自己創建的公司MySQL AB賣給了SUN,此後,隨著SUN被甲骨文收購MySQL的所有權也落入Oracle的手中.MariaDB名稱來自MichaelWidenius的女兒Maria的名字.



MariaDB 連接查詢

連接是關系數據庫模型的主要特點,連接查詢是關系數據庫中最主要的查詢,主要包括內連接、外連接等.通過連接運算符可以實現多個表查詢,在關系數據庫管理系統中,表建立時各數據之間的關系不必確定,常把一個實體的所有信息存放在一個表中.當查詢數據時,通過連接操作查詢出存放在多個表中的不同實體的信息.當兩個或多個表中存在相同意義的字段時,便可以通過這些字段對不同的表進行連接查詢.

◆內連接查詢◆

內連接(INNER JOIN)使用比較運算符進行表間(某些列)數據的比較操作,並列出這些表中與連接條件相匹配的數據行,組合成新記錄,也就是說,在內連接查詢中,只有滿足條件的記錄才能出現在結果關系中.

為了演示效果的需要,首先穿件一個suppliers

表,SQL語句如下:

MariaDB [lyshark]> create table suppliers
    -> (
    -> s_id int not null auto_increment,
    -> s_name char(50) not null,
    -> s_city char(50) null,
    -> s_zip char(10) null,
    -> s_call char(50) not null,
    -> primary key(s_id)
    -> );
Query OK, 0 rows affected (0.09 sec)

需要插入演示的數據,SQL語句如下:

INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(101,'FastFruit.','TianJin','30000','4521');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(102,'LT Supplies','ShangHai','554780','3268');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(103,'ACME LyShark','Chongqing','447581','9985');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(104,'FNK INCS','XiZang','3526','4475');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(105,'GOOD SET','ZhongSHan','4478511','6666');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(106,'JUST Eat Ours','TaiYuang','33325469','5555');
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call) values(107,'docker INC','ZhengZhou','1124574','4851');

內連接實例:lyshark表suppliers表之間使用內連接查詢.

1.在查詢之前先來看一下表結構吧.

MariaDB [lyshark]> desc lyshark;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| Uid   | char(10)     | NO   | PRI | NULL    |       |
| Gid   | int(11)      | NO   |     | NULL    |       |
| Name  | char(255)    | NO   |     | NULL    |       |
| Price | decimal(8,2) | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

MariaDB [lyshark]> desc suppliers;
+--------+----------+------+-----+---------+----------------+
| Field  | Type     | Null | Key | Default | Extra          |
+--------+----------+------+-----+---------+----------------+
| s_id   | int(11)  | NO   | PRI | NULL    | auto_increment |
| s_name | char(50) | NO   |     | NULL    |                |
| s_city | char(50) | YES  |     | NULL    |                |
| s_zip  | char(10) | YES  |     | NULL    |                |
| s_call | char(50) | NO   |     | NULL    |                |
+--------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

由上面的查詢結果可看到,lyshark表suppliers表中都有相同數據類型的字段ID,兩個表通過Gid與s_id字段建立聯系.

2.接下來從lyshark表查詢Name,Price字段,從suppliers表查詢s_id,s_name字段,SQL語句如下:

MariaDB [lyshark]> select suppliers.s_id,s_name,Name,Price
    -> from lyshark,suppliers
    -> where lyshark.Gid = suppliers.s_id;

+------+---------------+------------+-------+
| s_id | s_name        | Name       | Price |
+------+---------------+------------+-------+
|  101 | FastFruit.    | apple      |  5.20 |
|  103 | ACME LyShark  | apricot    |  2.20 |
|  101 | FastFruit.    | blackberry | 10.20 |
|  104 | FNK INCS      | berry      |  7.60 |
|  107 | docker INC    | xxxx       |  3.60 |
|  102 | LT Supplies   | orange     | 11.20 |
|  105 | GOOD SET      | melon      |  8.20 |
|  101 | FastFruit.    | cherry     |  3.20 |
|  104 | FNK INCS      | lemon      |  6.40 |
|  106 | JUST Eat Ours | mango      | 15.70 |
|  105 | GOOD SET      | xbabay     |  2.60 |
|  105 | GOOD SET      | xxtt       | 11.60 |
|  103 | ACME LyShark  | coconut    |  9.20 |
|  102 | LT Supplies   | bannana    | 10.30 |
|  102 | LT Supplies   | grape      |  5.30 |
|  107 | docker INC    | xbababa    |  3.60 |
+------+---------------+------------+-------+
16 rows in set (0.01 sec)

在這裏,SELECT語句與前面所介紹的一個最大的差別是,SELECT後面指定的列分別屬於兩個不同的表,(Name,Price)在表 lyshark中,而另外兩個字段在表 suppliers中,同時FROM子句列出了兩個表lyshark 和 suppliers.WHERE 子句在這裏作為過濾條件,指明只有兩個表中的s_id字段值相等的時候才符合連接查詢的條件.從返回的結果可以看到,顯示的記錄是由兩個表中不同列值組成的新記錄.

內連接(INNER JOIN)實例:lyshark表suppliers表之間,使用INNER JOIN語法進行內連接查詢,SQL語句如下:

MariaDB [lyshark]> select suppliers.s_id,s_name,Name,Price
    -> from lyshark INNER JOIN suppliers
    -> ON lyshark.Gid=suppliers.s_id;
+------+---------------+------------+-------+
| s_id | s_name        | Name       | Price |
+------+---------------+------------+-------+
|  101 | FastFruit.    | apple      |  5.20 |
|  103 | ACME LyShark  | apricot    |  2.20 |
|  101 | FastFruit.    | blackberry | 10.20 |
|  104 | FNK INCS      | berry      |  7.60 |
|  107 | docker INC    | xxxx       |  3.60 |
|  102 | LT Supplies   | orange     | 11.20 |
|  105 | GOOD SET      | melon      |  8.20 |
|  101 | FastFruit.    | cherry     |  3.20 |
|  104 | FNK INCS      | lemon      |  6.40 |
|  106 | JUST Eat Ours | mango      | 15.70 |
|  105 | GOOD SET      | xbabay     |  2.60 |
|  105 | GOOD SET      | xxtt       | 11.60 |
|  103 | ACME LyShark  | coconut    |  9.20 |
|  102 | LT Supplies   | bannana    | 10.30 |
|  102 | LT Supplies   | grape      |  5.30 |
|  107 | docker INC    | xbababa    |  3.60 |
+------+---------------+------------+-------+
16 rows in set (0.01 sec)

本案例和上面的查詢結果是一樣的,在這裏兩表之間的關系通過INNER JOIN指定,使用這種語法的時候連接的條件使用ON子句,ON和WHERE後面指定的條件相同.

自連接實例: 查詢供應商Uid=‘a1‘的水果的種類,SQL語句如下:

如果在一個連接查詢中,涉及的兩個表都是同一張表,這種查詢稱為自連接查詢,自連接是一種特殊的內連接,它是指相互連接的表在物理上為同一張表,但可以在邏輯上分為兩張表.

MariaDB [lyshark]> select f1.Uid,f1.Name
    -> from lyshark AS f1,lyshark AS f2 
    -> where f1.Gid = f2.Gid and f2.Uid='a1';
+-----+------------+
| Uid | Name       |
+-----+------------+
| a1  | apple      |
| b1  | blackberry |
| c0  | cherry     |
+-----+------------+
3 rows in set (0.01 sec)

此處查詢的兩個表是相同的表,為了防止產生二義性,對表使用了別名,lyshark表第1次出現的別名為fl,第2次出現的別名為f2,使用SELECT語句返回列時明確指出返回以n為前綴的列的全名,WHERE連接兩個表,並按照第2個表的Gid對數據進行過濾,返回所需數據.

◆外連接查詢◆

外連接查詢將查詢多個表中相關聯的行,內連接時,返回查詢結果集合中的僅是符合查詢條件和連接條件的行.但有時候需要包含沒有關聯的行中數據,即返回查詢結果集合中的不僅包含符合連接條件的行,而且還包括左表(左外連接或左連接),右表(右外連接或右連接),或兩個連接表(全外連接)中的所有數據行,外連接分為左外連接右外連接:

● LEFT JOIN(左連接):返回包括左表中的所有記錄和右表中連接字段相等的記錄.
● RIGHT JOIN(右連接):返回包括右表中的所有記錄和左表中連接字段相等的記錄.

接著下面先來創建兩個測試表orders和customers,SQL語句如下:

MariaDB [lyshark]> create table orders
    -> (
    -> o_num int not null auto_increment,
    -> o_date datetime not null,
    -> c_id int not null,
    -> primary key(o_num)
    -> );
Query OK, 0 rows affected (0.02 sec)

MariaDB [lyshark]> create table customers (c_id int not null );
Query OK, 0 rows affected (0.01 sec)

接著插入需要演示的數據,SQL語句如下:

INSERT INTO orders(o_num,o_date,c_id) VALUES(30001,'2018-09-01',10001);
INSERT INTO orders(o_num,o_date,c_id) VALUES(30002,'2018-09-02',10003);
INSERT INTO orders(o_num,o_date,c_id) VALUES(30003,'2018-09-03',10004);
INSERT INTO orders(o_num,o_date,c_id) VALUES(30004,'2018-09-04',10005);
INSERT INTO orders(o_num,o_date,c_id) VALUES(30005,'2018-09-05',10001);

INSERT INTO customers(c_id) VALUES(10001);
INSERT INTO customers(c_id) VALUES(10002);
INSERT INTO customers(c_id) VALUES(10003);
INSERT INTO customers(c_id) VALUES(10004);
INSERT INTO customers(c_id) VALUES(10005);

左連接(lEFT JOIN)

左連接的結果包括LEFT OUTER子句中指定的左表的所有行,而不僅僅是連接列所匹配的行,如果左表的某行在右表中沒有匹配行,則在相關聯的結果中,右表的所有選擇列表列均為空值.

如下:在customers表orders表中,查詢所有客戶,包括沒有訂單的客戶,SQL語句如下:

MariaDB [lyshark]> select customers.c_id,orders.o_num
    -> from customers LEFT OUTER JOIN orders
    -> ON customers.c_id=orders.c_id;
+-------+-------+
| c_id  | o_num |
+-------+-------+
| 10001 | 30001 |
| 10003 | 30002 |
| 10004 | 30003 |
| 10005 | 30004 |
| 10001 | 30005 |
| 10002 |  NULL |
+-------+-------+
6 rows in set (0.00 sec)

結果顯示了6條記錄,編號10002的用戶並沒有達成交易,所有該條記錄只取出了ordes表中相應的值,而從customers表中取出的值為空值NULL.

右連接(RIGHT JOIN)

右連接是左連接的反向連接,將返回右表的所有行,如果右表的某行在作表中沒有匹配行,作表將返回空值.
實例:customers表和orders表中,查詢所有訂單,包括沒有客戶的訂單,SQL語句如下:

MariaDB [lyshark]> select customers.c_id,orders.o_num
    -> from customers RIGHT OUTER JOIN orders
    -> ON customers.c_id=orders.c_id;
+-------+-------+
| c_id  | o_num |
+-------+-------+
| 10001 | 30001 |
| 10001 | 30005 |
| 10003 | 30002 |
| 10004 | 30003 |
| NULL  | 30004 |
+-------+-------+
5 rows in set (0.00 sec)

結果顯示6條記錄,30004訂單客戶取消了訂單,對應的customers表中並沒有該客戶的信息,所以該條記錄只取出了orders表中相應的值,而從customers表中取出的值為空值NULL.

◆復合連接查詢◆

復合條件連接查詢是在連接查詢的過程中,通過添加過濾條件,限制查詢的結果,使查詢結果更精確.
實例:lyshark表和suppliers表之間,使用INNER JOIN語法進行內連接查詢,並對查詢結果排序,SQL語句如下:

MariaDB [lyshark]> select suppliers.s_id,s_name,Name,Price
    -> from lyshark INNER JOIN suppliers
    -> ON lyshark.Gid = suppliers.s_id
    -> ORDER BY lyshark.Gid;
+------+---------------+------------+-------+
| s_id | s_name        | Name       | Price |
+------+---------------+------------+-------+
|  101 | FastFruit.    | apple      |  5.20 |
|  101 | FastFruit.    | blackberry | 10.20 |
|  101 | FastFruit.    | cherry     |  3.20 |
|  102 | LT Supplies   | grape      |  5.30 |
|  102 | LT Supplies   | bannana    | 10.30 |
|  102 | LT Supplies   | orange     | 11.20 |
|  103 | ACME LyShark  | apricot    |  2.20 |
|  103 | ACME LyShark  | coconut    |  9.20 |
|  104 | FNK INCS      | lemon      |  6.40 |
|  104 | FNK INCS      | berry      |  7.60 |
|  105 | GOOD SET      | xbabay     |  2.60 |
|  105 | GOOD SET      | xxtt       | 11.60 |
|  105 | GOOD SET      | melon      |  8.20 |
|  106 | JUST Eat Ours | mango      | 15.70 |
|  107 | docker INC    | xxxx       |  3.60 |
|  107 | docker INC    | xbababa    |  3.60 |
+------+---------------+------------+-------+
16 rows in set (0.00 sec)


MariaDB 子查詢

子查詢指一個查詢語句嵌套在另一個查詢語句內部的查詢,在SELECT子句中先計算子查詢,子查詢結果作為外層另一個查詢的過濾條件,查詢可以基於一個表或者多個表.
一般的子查詢中常用的操作符有ANY(SOME),ALL,IN,EXISTS.子查詢可以添加到SELECT、UPDATE和DELETE 語句中,而且可以進行多層嵌套.子查詢中也可以使用比較運算符,如<,<=,>,>=,!=等.

◆IN 子查詢◆

IN關鍵字進行子查詢時,內層查詢語句僅僅返回一個數據列,這個數據列裏的值將提供給外層查詢語句進行比較操作.

IN查詢1: 查詢lyshark表中的Uid=‘a1‘的GId號,並以Gid作為查詢條件查詢suppliers表s_id字段s_city字段的數值.

MariaDB [lyshark]> select Gid from lyshark where Uid='a1';
+-----+
| Gid |
+-----+
| 101 |
+-----+
1 row in set (0.00 sec)

MariaDB [lyshark]> select * from suppliers;
+------+---------------+-----------+----------+--------+
| s_id | s_name        | s_city    | s_zip    | s_call |
+------+---------------+-----------+----------+--------+
|  101 | FastFruit.    | TianJin   | 30000    | 4521   |
|  102 | LT Supplies   | ShangHai  | 554780   | 3268   |
|  103 | ACME LyShark  | Chongqing | 447581   | 9985   |
|  104 | FNK INCS      | XiZang    | 3526     | 4475   |
|  105 | GOOD SET      | ZhongSHan | 4478511  | 6666   |
|  106 | JUST Eat Ours | TaiYuang  | 33325469 | 5555   |
|  107 | docker INC    | ZhengZhou | 1124574  | 4851   |
+------+---------------+-----------+----------+--------+
7 rows in set (0.00 sec)

MariaDB [lyshark]> select s_city from suppliers where s_id IN
    -> (select Gid from lyshark where Uid='a1');
+---------+
| s_city  |
+---------+
| TianJin |
+---------+
1 row in set (0.02 sec)

IN查詢2: 查詢lyshark表中,Gid字段是(101和105)編號的內容.

MariaDB [lyshark]> select Gid,Name from lyshark where Gid IN(101,105);
+-----+------------+
| Gid | Name       |
+-----+------------+
| 101 | apple      |
| 101 | blackberry |
| 105 | melon      |
| 101 | cherry     |
| 105 | xbabay     |
| 105 | xxtt       |
+-----+------------+
6 rows in set (0.00 sec)

NOT IN查詢: 這個查詢結果正好和上面的例子相反.

MariaDB [lyshark]> select Gid,Name from lyshark where Gid NOT IN(101,105,102);
+-----+----------+
| Gid | Name     |
+-----+----------+
| 103 | apricot  |
| 104 | berry    |
| 107 | xxxx     |
| 104 | lemon    |
| 999 | lysharks |
| 106 | mango    |
| 103 | coconut  |
| 107 | xbababa  |
+-----+----------+
8 rows in set (0.00 sec)

◆ANY 子查詢◆

ANY和SOME關鍵字是同義詞,表示滿足其中任意一個條件,他們允許創建一個表達式對子查詢的返回值進行比較,只要滿足內層子查詢中任何一個比較條件,就返回一個結果作為外層查詢的條件.

為了進行下面的實驗,先來創建一下SQL語句表格:

MariaDB [lyshark]> create table tab1(num1 int not null);
Query OK, 0 rows affected (0.02 sec)

MariaDB [lyshark]> create table tab2(num2 int not null);
Query OK, 0 rows affected (0.00 sec)

INSERT INTO tab1 VALUES(1),(5),(13),(27);
INSERT INTO tab2 VALUES(6),(14),(11),(20);

ANY 實例: 返回tab2表的所有num2列,然後將tab1中的num1的值與之進行比較,只要大於num2的任何1個值,即為符合查詢結果.

MariaDB [lyshark]> select num1 from tab1 where num1 > ANY(select num2 from tab2);
+------+
| num1 |
+------+
|   13 |
|   27 |
+------+
2 rows in set (0.01 sec)

在子查詢中,返回的是tab2的所有num2列結果(6,14,11,20),然後將tab1中的num1列的值與之進行比較,只要大於num2列的任意一個數即為符合條件的結果.

◆ALL 子查詢◆

ALL關鍵字與ANY不同,使用ALL時需要同時滿足所有內層查詢的條件,ALL關鍵字接在一個比較操作符的後面,表示與子查詢返回的所有值比較為TRUE,則返回TRUE.

ALL實例: 返回tab2表中比tab2表num2列所有值都打的值,SQL語句如下:

MariaDB [lyshark]> select num1 from tab1 where num1 > ALL(select num2 from tab2);
+------+
| num1 |
+------+
|   27 |
+------+
1 row in set (0.02 sec)

以上,大於所有num2列的num1值只有27,則返回27.

◆EXISTS 子查詢◆

EXISTS關鍵字後面的參數是一個任意的子查詢,系統對子查詢進行運算以判斷它是否返回行,如果至少返回一行,那麽EXISTS的結果為true,此時外層查詢語句將進行查詢.如果子查詢沒有返回任何行,那麽EXISTS返回的結果是false,此時外層語句將不進行查詢.

EXISTS 實例1: 查詢lyshark表中所有記錄,查詢suppliers表中是否存在s_id=107的記錄,如果存在,則查詢lyshark表中的記錄,否則不查詢,SQL語句如下:

MariaDB [lyshark]> select * from lyshark
    -> where EXISTS
    -> (select s_name from suppliers where s_id=107);
+---------+-----+------------+--------+
| Uid     | Gid | Name       | Price  |
+---------+-----+------------+--------+
| a1      | 101 | apple      |   5.20 |
| a2      | 103 | apricot    |   2.20 |
| b1      | 101 | blackberry |  10.20 |
| b2      | 104 | berry      |   7.60 |
| b5      | 107 | xxxx       |   3.60 |
| bs1     | 102 | orange     |  11.20 |
| bs2     | 105 | melon      |   8.20 |
| c0      | 101 | cherry     |   3.20 |
| l2      | 104 | lemon      |   6.40 |
| lyshark | 999 | lysharks   | 999.00 |
| m1      | 106 | mango      |  15.70 |
| m2      | 105 | xbabay     |   2.60 |
| m3      | 105 | xxtt       |  11.60 |
| o2      | 103 | coconut    |   9.20 |
| t1      | 102 | bannana    |  10.30 |
| t2      | 102 | grape      |   5.30 |
| t4      | 107 | xbababa    |   3.60 |
+---------+-----+------------+--------+
17 rows in set (0.01 sec)

由結果可以看到,內層查詢結果表明suppliers表中存在s_id =107表達式返回true,外層查詢語句接收true 之後對表lyshark進行查詢,並返回所有的記錄.

EXISTS 實例2: 查詢suppliers表中是否存在s_id=107的字段,如果存在,則查詢lyshark表中的Price大於10.02的記錄,SQL語句如下:

MariaDB [lyshark]> select * from lyshark
    -> where Price >10.02 AND EXISTS
    -> (select s_name from suppliers where s_id=107);
+---------+-----+------------+--------+
| Uid     | Gid | Name       | Price  |
+---------+-----+------------+--------+
| b1      | 101 | blackberry |  10.20 |
| bs1     | 102 | orange     |  11.20 |
| lyshark | 999 | lysharks   | 999.00 |
| m1      | 106 | mango      |  15.70 |
| m3      | 105 | xxtt       |  11.60 |
| t1      | 102 | bannana    |  10.30 |
+---------+-----+------------+--------+
6 rows in set (0.00 sec)

NOT EXISTS 實例: 查詢suppliers表中是否存在s_id=107的供應商,如果不存在則查詢lyshark表中的記錄,SQL語句如下:

MariaDB [lyshark]> select * from lyshark
    -> where NOT EXISTS
    -> (select s_name from suppliers where s_id=107);
Empty set (0.00 sec)

如上:查詢語句select s_name from suppliers where s_id=107返回false,則不再執行外層的查詢工作.

◆比較運算符子查詢◆

1111

MariaDB 其他查詢

合並查詢結果

為表和字段取別名

MariaDB 連接查詢與子查詢(6)