MariaDB 连接查询与子查询
Posted LyShark
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MariaDB 连接查询与子查询相关的知识,希望对你有一定的参考价值。
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 连接查询与子查询的主要内容,如果未能解决你的问题,请参考以下文章