MySQL 基础入门
Day4 MySQL 基础 (三)- 表联结
一、学习内容
1. MySQL别名
参考教材:http://www.runoob.com/sql/sql-alias.html
基本上,创建别名是为了让列名称的可读性更强。
- 列别名
有时,列的名称是一些表达式,使查询的输出很难理解。要给列一个描述性名称,可以使用列别名。
要给列添加别名,可以使用AS关键词后跟别名。
# 列的 SQL 别名语法:
SELECT column_name AS alias_name
FROM table_name;
- 表别名
可以使用别名为表添加不同的名称。使用AS关键字在表名称分配别名。
# 表的 SQL 别名语法:
SELECT column_name(s)
FROM table_name AS alias_name;
2. INNER JOIN
参考教材:https://www.yiibai.com/mysql/inner-join.html
INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录。
# 语法:
SELECT column_list
FROM t1
INNER JOIN t2 ON join_condition1
INNER JOIN t3 ON join_condition2
...
WHERE where_conditions;
# 假设使用 INNER JOIN 子句连接两个表:t1和t2,我们来简化上面的语法。
SELECT column_list
FROM t1
INNER JOIN t2 ON join_condition;
3. LEFT JOIN
参考教材:https://www.yiibai.com/mysql/left-join.html
LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录。
# 写法:
SELECT
t1.c1, t1.c2, t2.c1, t2.c2
FROM
t1
LEFT JOIN
t2 ON t1.c1 = t2.c1;
4. CROSS JOIN
参考教材:https://www.yiibai.com/mysql/cross-join.html
CROSS JOIN又称为笛卡尔乘积,实际上是把两个表乘起来。
# 写法:
SELECT * FROM table1 CROSS JOIN table2
5. 自连接
参考教材:https://www.yiibai.com/mysql/self-join.html
自连接(self join)是SQL语句中经常要用的连接方式,使用自连接可以将自身表的一个镜像当作另一个表来对待,从而能够得到一些特殊的数据。
# 写法:
SELECT column_name(s)
FROM table1 T1, table1 T2
WHERE condition;
6. UNION
参考教材:http://www.runoob.com/mysql/mysql-union-operation.html
-
概念:MySQL UNION 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。
-
语法:
# 写法:
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions]
UNION [ALL | DISTINCT]
SELECT expression1, expression2, ... expression_n
FROM tables
[WHERE conditions];
- 参数:
- expression1, expression2, … expression_n: 要检索的列。
- tables: 要检索的数据表。
- WHERE conditions: 可选, 检索条件。
- DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没啥影响。
- ALL: 可选,返回所有结果集,包含重复数据。
7. 以上几种方式的区别和联系
参考教材:
- http://www.zsythink.net/archives/1105
- http://justcode.ikeepstudying.com/2016/08/mysql-图解-inner-join、left-join、right-join、full-outer-join、union、union-all的区别/
二、作业
项目五:组合两张表 (难度:简单)
在数据库中创建表1和表2,并各插入三行数据(自己造)
表1: Person
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| PersonId | int |
| FirstName | varchar |
| LastName | varchar |
+-------------+---------+
PersonId 是上表主键
表2: Address
+-------------+---------+
| 列名 | 类型 |
+-------------+---------+
| AddressId | int |
| PersonId | int |
| City | varchar |
| State | varchar |
+-------------+---------+
AddressId 是上表主键
编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:FirstName, LastName, City, State
# 创建表1
mysql> CREATE TABLE Person (
-> PersonId INT NOT NULL PRIMARY KEY,
-> FirstName VARCHAR(20) NULL,
-> LastName VARCHAR(20) NULL
-> );
Query OK, 0 rows affected (0.23 sec)
# 插入数据(方法一:一次性插入)
mysql> INSERT INTO Person (PersonId, FirstName, LastName) VALUES (1, 'Carine', '
Schmitt'), (2, 'Jean', 'King'), (3, 'Jeff', 'Young');
Query OK, 3 rows affected (0.06 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 插入数据(方法二:一个一个插入)
mysql> INSERT INTO Person (PersonId, FirstName, LastName) VALUES (1, 'Carine', 'Schmitt');
Query OK, 1 row affected (0.05 sec)
mysql> INSERT INTO Person (PersonId, FirstName, LastName) VALUES (2, 'Jean', 'King');
Query OK, 1 row affected (0.05 sec)
mysql> INSERT INTO Person (PersonId, FirstName, LastName) VALUES (3, 'Jeff', 'Young');
Query OK, 1 row affected (0.08 sec)
# 创建表2
mysql> CREATE TABLE Address (
-> AddressId INT NOT NULL PRIMARY KEY,
-> PersonId INT NULL,
-> City VARCHAR(50) NULL,
-> State VARCHAR(50) NULL
-> );
Query OK, 0 rows affected (0.26 sec)
# 插入数据(方法一:一次性插入)
mysql> INSERT INTO Address (AddressId, PersonId, City, State) VALUES (11, 3, 'Na
ntes', 'NV'), (12, 2, 'NYC', 'NY'), (13, 1, 'Melbourne', 'CA');
Query OK, 3 rows affected (0.06 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 插入数据(方法二:一条一条插入)
mysql> INSERT INTO Address (AddressId, PersonId, City, State) VALUES (11, 3, 'Nantes', 'NV');
Query OK, 1 row affected (0.05 sec)
mysql> INSERT INTO Address (AddressId, PersonId, City, State) VALUES (12, 2, 'NYC', 'NY');
Query OK, 1 row affected (0.05 sec)
mysql> INSERT INTO Address (AddressId, PersonId, City, State) VALUES (13, 1, 'Melbourne', 'CA');
Query OK, 1 row affected (0.06 sec)
# 无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:FirstName, LastName, City, State
mysql> SELECT Person.FirstName, Person.LastName, Address.City, Address.State
-> FROM Person
-> LEFT JOIN Address
-> ON Person.PersonId = Address.PersonId;
+-----------+----------+-----------+-------+
| FirstName | LastName | City | State |
+-----------+----------+-----------+-------+
| Jeff | Young | Nantes | NV |
| Jean | King | NYC | NY |
| Carine | Schmitt | Melbourne | CA |
+-----------+----------+-----------+-------+
3 rows in set (0.00 sec)
项目六:删除重复的邮箱(难度:简单)
编写一个 SQL 查询,来删除 email 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
Id 是这个表的主键。
例如,在运行你的查询语句之后,上面的 Person表应返回以下几行:
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
+----+---------+
# 查询 email 表中的重复邮箱
mysql> SELECT e1.*
-> FROM email e1,
-> email e2
-> WHERE e1.Email = e2.Email AND e1.Id > e2.Id;
+----+---------+
| ID | Email |
+----+---------+
| 3 | a@b.com |
+----+---------+
1 row in set (0.02 sec)
# 删除 email 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个
mysql> DELETE e1 FROM email e1, email e2
-> WHERE e1.Email = e2.Email AND e1.Id > e2.Id;
Query OK, 1 row affected (0.04 sec)
# 查询删除重复邮箱后的 email 表
mysql> SELECT * FROM email;
+----+---------+
| ID | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
+----+---------+
2 rows in set (0.00 sec)