SQL查询从多个表返回数据

我想知道以下几点:

  • 如何从数据库中的多个表中获取数据
  • 有哪些类型的方法可以做到这一点
  • 什么是连接和联合,它们之间有什么不同
  • 我应该在什么时候使用每一个来比较其他的

我计划在我的(例如-PHP)应用程序中使用它,但不想对数据库运行多个查询,在一个查询中从多个表获取数据需要哪些选项

注意:我写这篇文章是因为我希望能够链接到一个关于我在PHP队列中经常遇到的许多问题的编写良好的指南,因此我可以在发布答案时链接到该指南以了解更多细节

答案包括以下几点:

  1. 第1部分-连接和联合
  2. 第2部分-子查询
  3. 第3部分-技巧和高效代码
  4. 第4部分-From子句中的子查询
  5. 第五部分-约翰的把戏

第1部分-连接和联合

答案包括:

  1. 第一部分
    • 使用内部联接联接两个或多个表(有关其他信息,请参阅wikipedia条目)
    • 如何使用联合查询
    • 左侧和右侧外部联接(此stackOverflow答案非常适合描述联接类型)
    • Intersect查询(以及在数据库不支持的情况下如何复制它们)——这是SQL Server的一个功能(请参见信息),也是我首先编写这整篇文章的部分原因
  2. 第二部分
    • 子查询-它们是什么、在哪里可以使用以及需要注意什么
    • 笛卡尔加入阿卡-哦,不幸

有许多方法可以从数据库中的多个表中检索数据。在这个答案中,我将使用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秒)

另一种可能更常用,称为表别名。本例中的表有简单的好名字和短名字,但类型是

发表评论