文章目录
- MySQL别名
- 1.MySQL列的别名
- 2.给表起别名
- 表连接
- 1.where字句连接
- 2. INNER JOIN
- 3. LEFT JOIN
- 4. CROSS JOIN
- 5. 自连接
- 6. UNION
- UNION规则
- UNION 与UNION ALL
- UNION与ORDER BY子句结合
- 练习
MySQL别名
1.MySQL列的别名
- 给表达式起列名
有时,select语句中会包含一些表达式,为了更好地理解这些表达式的含义,增加可读性,需要给表达式起一个列名,以下是它的基本语法:
SELECT
[column_1 | expression] AS descriptive_name
FROM table_name;
- 引用列别名
在MySQL中,ORDER BY,GROUP BY和HAVING子句中可以使用列别名来引用该列,但是where字句中不可以引用列别名。
补充:若列名包含空格,则列名要加上单引号。 AS也可省略不写。
示例:利用orderdetails表,按订单号列出每个订单下的销售额,并且要求销售额大于50000。
SELECT orderNumber AS orN,SUM(priceEach*quantityOrdered) AS sales
FROM orderdetails
GROUP BY orN
HAVING sales > 50000
ORDER BY sales DESC
2.给表起别名
table_name AS table_alias
- 引用表别名
- 一般在INNER JOIN,LEFT JOIN,self join子句中使用表别名来简化代码(见INNER JOIN的示例)
- 还可以用在selec的t列表, ORDER BY,GROUP BY和HAVING等字句中。
表连接
1.where字句连接
SELECT ordt.orderNumber,status
FROM orderdetails AS ordt,orders AS ord
WHERE ordt.orderNumber = ord.orderNumber
- 若select中的列来自多个表,则需要指定该列来自哪个表
- where子句也可以连接多个表,用and连接即可
2. INNER JOIN
内连接也称为等值连接,它基于两个表之间的相等测试
SELECT column_list
FROM t1
INNER JOIN t2 ON join_condition
INNER JOIN t3 ON join_condition2
…
WHERE where_conditions
- 首先,在FROM子句中指定主表。
- 其次,表中要连接的主表应该出现在INNER JOIN子句中。理论上说,可以连接多个其他表。 但是,为了获得更好的性能,应该限制要连接的表的数量(最好不要超过三个表)。
- 第三,连接条件或连接谓词。连接条件出现在INNER JOIN子句的ON关键字之后。连接条件是将主表中的行与其他表中的行进行匹配的规则。
- 连接原理:第一个表的每一行与第二个表中的每一行匹配,直到遍历完第二个表,接着第一个表的每一行与第二个表中的每一行匹配,直到遍历完第二个表,再重复以上操作,直到第一个表也遍历完成。
示例:连接orderdetails和orders表并使用表别名。
SELECT *
FROM orderdetails As ordt
INNER JOIN orders AS ord
ON ordt.orderNumber=ord.orderNumber
3. LEFT JOIN
LEFT JOIN子句允许从匹配的左右表中查询选择行记录,连接左表(t1)中的所有行,即使在右表(t2)中找不到匹配的行也显示出来,但使用NULL值代替。
SELECT
t1.c1, t1.c2, t2.c1, t2.c2
FROM
t1
LEFT JOIN
t2 ON t1.c1 = t2.c1;
4. CROSS JOIN
cross join是笛卡尔积,就是不加条件限制,即没有on字句的连接。该连接返回的行数为两个表行数的乘积。
SELECT *
FROM T1
CROSS JOIN
T2;
如果添加了WHERE子句,如果T1和T2有关系,则CROSS JOIN的工作方式与INNER JOIN子句类似。
5. 自连接
- 当您想将表中行与同一表中的其他行组合时,可以使用自连接。要执行自联接操作必须使用表别名来帮助MySQL在单个查询中区分左表与同一张表的右表。
- 为了更加直接地理解自连接,下面将通过一个例子来帮助你来理解。
示例:在employees表中,employeeNumber 和report to 有重复值,这是因为下级的上一级还有他自己上一级的领导,所以这两列是有重复值的,那么假如我想知道所有上级领导直接管理的下级员工,要怎么实现这个查询呢?
思路:若是我们可以复制一份empolyees表,然后将这两个表的report to和employeeNumber字段连接,就可以找出管理者的姓名和它的直属员工的姓名,这也是一种解决方法。在这里我们也可以使用自连接,将表自己跟自己连接,而不用再去复制它。用自连接实现过程如下:
SELECT *
FROM employees a
INNER JOIN
employees b
ON
a.reportsTo=b.employeeNumber
从上图可以看到左半部分的表时员工,右半部分的表是管理者
接下来我们提取他们的名字
SELECT CONCAT(a.lastName," “,a.firstName) AS employee,
CONCAT(b.lastName,” ",b.firstName) AS manager
FROM employees a
INNER JOIN
employees b
ON
a.reportsTo=b.employeeNumber
结果如下:
6. UNION
union组合查询可以将多条select语句的结果组合成一个结果集。相当于将多个表按相同字段值纵向联结。
SELECT 列名称 FROM 表名称 UNION SELECT 列名称 FROM 表名称 ORDER BY 列名称;
SELECT 列名称 FROM 表名称 UNION ALL SELECT 列名称 FROM 表名称 ORDER BY 列名称;
UNION规则
- 必须由两条或两条以上的select语句组成,语句之间用关键字UNION分隔因此如果有四条语句,则要使用三个UNION。
- UNION中的每个查询必须至少包含有一个相同的列、表达式或聚集函数
- 列数据类型必须兼容,类型不必完全相同,但必须是DBMS可以隐含转换的数据类型。(因为有时候要把两个不同列的数据合并为一列)
UNION 与UNION ALL
UNION默认消除重复行,若要匹配到所有行,需使用 UNION ALL。
UNION与ORDER BY子句结合
在使用UNION组合查询时,只允许使用使用一条ORDER BY子句,而且它必须位于最后一句select语句之后,这样操作的含义是对组合的结果集进行排序,组合查询不能对单个SELECT语句排序。
练习
项目五:组合两张表 (难度:简单)
在数据库中创建表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。
创建表代码:
CREATE TABLE Person(
PersonId INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50)
)INSERT INTO Person
VALUES(1,“a”,“A”),
(2,“b”,“B”),
(3,“c”,“C”)CREATE TABLE Address(
Addressid INT PRIMARY KEY,
Personid INT,
City VARCHAR(8),
State VARCHAR(20)
)INSERT INTO Address
VALUES(1.1,1,“china”,“Asia”),
(2.2,2,“english”,“Europe”),
(4.4,4,“america”,“America”)
查询代码:
SELECT Person.Personid,FirstName,LastName,City,State
FROM Person
LEFT JOIN
Address
ON
Person.Personid=Address.Personid
输出结果:
项目六:删除重复的邮箱(难度:简单)
编写一个 SQL 查询,来删除 email 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。
±—±--------+
| Id | Email |
±—±--------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
±—±--------+
Id 是这个表的主键。
例如,在运行你的查询语句之后,上面的 Email表应返回以下几行:
±—±-----------------+
| Id | Email |
±—±-----------------+
| 1 | a@b.com |
| 2 | c@d.com |
±—±-----------------+
DELETE FROM email
WHERE ID NOT in(
SELECT ID_min FROM(
SELECT Email,MIN(Id) AS ID_min
FROM email
GROUP BY Email
) AS a
)SELECT * FROM email
输出结果: