我想知道以下几点:
- 如何从数据库中的多个表中获取数据
- 有哪些类型的方法可以做到这一点
- 什么是连接和联合,它们之间有什么不同
- 我应该在什么时候使用每一个来比较其他的
我计划在我的(例如-PHP)应用程序中使用它,但不想对数据库运行多个查询,在一个查询中从多个表获取数据需要哪些选项
注意:我写这篇文章是因为我希望能够链接到一个关于我在PHP队列中经常遇到的许多问题的编写良好的指南,因此我可以在发布答案时链接到该指南以了解更多细节
答案包括以下几点:
- 第1部分-连接和联合
- 第2部分-子查询
- 第3部分-技巧和高效代码
- 第4部分-From子句中的子查询
- 第五部分-约翰的把戏
第1部分-连接和联合
答案包括:
- 第一部分
- 使用内部联接联接两个或多个表(有关其他信息,请参阅wikipedia条目)
- 如何使用联合查询
- 左侧和右侧外部联接(此stackOverflow答案非常适合描述联接类型)
- Intersect查询(以及在数据库不支持的情况下如何复制它们)——这是SQL Server的一个功能(请参见信息),也是我首先编写这整篇文章的部分原因
- 第二部分
- 子查询-它们是什么、在哪里可以使用以及需要注意什么
- 笛卡尔加入阿卡-哦,不幸
有许多方法可以从数据库中的多个表中检索数据。在这个答案中,我将使用ANSI-92连接语法。这可能不同于其他一些使用较旧ANSI-89语法的教程(如果您习惯使用ANSI-89语法,可能看起来不那么直观,但我只能说尝试一下),因为当查询开始变得更复杂时,它更容易理解。为什么要用它?是否有性能提升?简短的回答是否定的,但一旦你习惯了,它就更容易阅读了。使用这种语法阅读其他人编写的查询更容易
我还将使用一个小型停车场的概念,这个停车场有一个数据库来跟踪它有哪些可用的汽车。店主雇用你作为他的IT计算机人员,希望你能够立即向他提供他所要求的数据
我制作了许多查找表,最终的表将使用这些表。这将为我们提供一个合理的工作模型。首先,我将针对具有以下结构的示例数据库运行查询。我将试着思考开始时所犯的常见错误,并解释这些错误的原因——当然,也会展示如何纠正这些错误
第一张表只是一个颜色列表,这样我们就知道停车场里有什么颜色
mysql>;创建表颜色(id int(3)非空自动增量主键,
-&彩色varchar(15),油漆varchar(10));
查询正常,0行受影响(0.01秒)
mysql>;从颜色显示列;
+-------+-------------+------+-----+---------+----------------+
|字段|类型|空|键|默认|额外|
+-------+-------------+------+-----+---------+----------------+
|id | int(3)| NO | PRI | NULL |自动增量|
|颜色| varchar(15)|是| |空||
|油漆| varchar(10)|是| |空||
+-------+-------------+------+-----+---------+----------------+
一组3行(0.01秒)
mysql>;插入颜色(颜色、油漆)值(“红色”、“金属色”),
-&燃气轮机;(“绿色”、“光泽”)、(“蓝色”、“金属色”),
-&燃气轮机;(‘白色’‘光泽’)、(‘黑色’‘光泽’);
查询正常,5行受影响(0.00秒)
记录:5个重复:0警告:0
mysql>;从颜色中选择*;
+----+-------+----------+
|id |颜色|油漆|
+----+-------+----------+
|1 |红色|金属色|
|2 |绿色|光泽|
|3 |蓝色|金属色|
|4 |白色|光泽|
|5 |黑色|光泽|
+----+-------+----------+
一组5行(0.00秒)
品牌表确定了停车场可能销售的不同品牌的汽车
mysql>;创建表品牌(id int(3)非空自动增量主键,
-&品牌varchar(15));
查询正常,0行受影响(0.01秒)
mysql>;展示品牌栏目;
+-------+-------------+------+-----+---------+----------------+
|字段|类型|空|键|默认|额外|
+-------+-------------+------+-----+---------+----------------+
|id | int(3)| NO | PRI | NULL |自动增量|
|品牌| varchar(15)|是| |空||
+-------+-------------+------+-----+---------+----------------+
一组2行(0.01秒)
mysql>;插入品牌(品牌)价值(“福特”)、(“丰田”),
-&燃气轮机;('Nissan')、('Smart')、('BMW');
查询正常,5行受影响(0.00秒)
记录:5个重复:0警告:0
mysql>;从品牌中选择*;
+----+--------+
|id |品牌|
+----+--------+
|1 |福特|
|2 |丰田|
|3 |日产|
|4 |聪明|
|5 |宝马|
+----+--------+
一组5行(0.00秒)
模型表将涵盖不同类型的汽车,使用不同的汽车类型比使用实际的汽车模型更简单
mysql>;创建表模型(id int(3)非空自动增量主键,
-&模型varchar(15));
查询正常,0行受影响(0.01秒)
mysql>;显示模型中的列;
+-------+-------------+------+-----+---------+----------------+
|字段|类型|空|键|默认|额外|
+-------+-------------+------+-----+---------+----------------+
|id | int(3)| NO | PRI | NULL |自动增量|
|模型| varchar(15)|是| |空||
+-------+-------------+------+-----+---------+----------------+
一组2行(0.00秒)
mysql>;插入车型(模型)值(“运动型”)、(“轿车”)、(“四轮驱动”)、(“豪华型”);
查询正常,4行受影响(0.00秒)
记录:4个重复:0警告:0
mysql>;从模型中选择*;
+----+--------+
|id |模型|
+----+--------+
|1 |体育|
|2辆轿车|
|3 |四轮驱动|
|4 |豪华|
+----+--------+
一组4行(0.00秒)
最后,把所有其他的桌子绑起来,把所有东西绑在一起的桌子。ID字段实际上是用于识别车辆的唯一批号
mysql>;创建表cars(id int(3)非空自动增量主键,
-&颜色国际(3)、品牌国际(3)、型号国际(3));
查询正常,0行受影响(0.01秒)
mysql>;显示来自汽车的专栏;
+-------+--------+------+-----+---------+----------------+
|字段|类型|空|键|默认|额外|
+-------+--------+------+-----+---------+----------------+
|id | int(3)| NO | PRI | NULL |自动增量|
|颜色| int(3)|是| |空||
|品牌| int(3)|是| |空||
|模型| int(3)|是| |空||
+-------+--------+------+-----+---------+----------------+
一组4行(0.00秒)
mysql>;插入汽车(颜色、品牌、型号)值(1,2,1)、(3,1,2)、(5,3,1),
-&燃气轮机;(4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
查询正常,受影响的10行(0.00秒)
记录:10个重复:0警告:0
mysql>;从汽车中选择*;
+----+-------+-------+-------+
|id |颜色|品牌|型号|
+----+-------+-------+-------+
| 1 | 1 | 2 | 1 |
| 2 | 3 | 1 | 2 |
| 3 | 5 | 3 | 1 |
| 4 | 4 | 4 | 2 |
| 5 | 2 | 2 | 3 |
| 6 | 3 | 5 | 4 |
| 7 | 4 | 1 | 3 |
| 8 | 2 | 2 | 1 |
| 9 | 5 | 2 | 3 |
| 10 | 4 | 5 | 1 |
+----+-------+-------+-------+
一组10行(0.00秒)
这将为我们提供足够的数据(我希望)来覆盖下面不同类型联接的示例,并提供足够的数据使它们有价值
因此,在这件事上,老板想知道他所有跑车的ID
这是一个简单的两表联接。我们有一个表,用于标识模型和表中的可用库存。如您所见,cars表的model列中的数据与我们拥有的cars表的models列相关。现在,我们知道models表的ID为1表示Sports,所以让我们编写连接
选择
身份证件
模型
从…起
汽车
加入模型
在model=ID上
所以这个查询看起来不错,对吗?我们已经确定了这两个表并包含了我们需要的信息,并且使用了一个正确标识要连接哪些列的连接
错误1052(23000):字段列表中的“ID”列不明确
哦,不!我们的第一个查询中出现错误!是的,它是李子。您知道,查询确实得到了正确的列,但其中一些列存在于两个表中,因此数据库对实际列的含义和位置感到困惑。有两种解决方案。第一个很简单,我们可以使用tableName.columnName来准确地告诉数据库我们的意思,如下所示:
选择
身份证,
模型
从…起
汽车
加入模型
在汽车上。model=models.ID
+----+--------+
|ID |模型|
+----+--------+
|1 |体育|
|3 |体育|
|8 |体育|
|10 |体育|
|2辆轿车|
|4 |轿车|
|5 |四轮驱动|
|7 |四轮驱动|
|9 |四轮驱动|
|6 |豪华|
+----+--------+
一组10行(0.00秒)
另一种可能更常用,称为表别名。本例中的表有简单的好名字和短名字,但类型是