何时使用左外连接?

时间:2011-05-03 19:39:47

标签: mysql sql database-design join

我不理解左外连接,右外连接的概念,或者我们为什么需要使用连接!我正在努力解决的问题和我正在处理的表格是:Link

问题3(b)

在SQL中构造一个命令来解决以下查询,解释为什么必须使用它 (外部)连接方法。 [5分] “找出每个工作人员及其受抚养配偶的姓名,如果有的话”

问题3(c) -

在SQL中构造一个命令来解决以下查询,使用(i)连接方法,以及(ii) 子查询方法。 [10分] “找到每个工作时间超过20小时的工作人员的身份名称 电脑化项目“

有人可以向我解释一下吗?

5 个答案:

答案 0 :(得分:80)

联接用于将两个相关表组合在一起。

在您的示例中,您可以组合Employee表和Department表,如下所示:

SELECT FNAME, LNAME, DNAME
FROM
EMPLOYEE INNER JOIN DEPARTMENT ON EMPLOYEE.DNO=DEPARTMENT.DNUMBER

这会产生如下记录集:

FNAME   LNAME   DNAME
-----   -----   -----
John    Smith   Research
John    Doe     Administration

我上面使用了INNER JOININNER JOIN组合了两个表,以便显示两个表中仅匹配记录,并且在这种情况下,它们连接,在部门编号上(字段DNO)在员工中,部门表中的DNUMBER)。

LEFT JOIN允许您在第一个表中有记录时组合两个表,但可能不在第二个表中有记录。例如,假设您需要所有员工以及任何家属的列表:

SELECT EMPLOYEE.FNAME as employee_first, EMPLOYEE.LNAME as employee_last, DEPENDENT.FNAME as dependent_last, DEPENDENT.LNAME as dependent_last
FROM
EMPLOYEE INNER JOIN DEPENDENT ON EMPLOYEE.SSN=DEPENDENT.ESSN

这里的问题是,如果员工没有有依赖关系,那么他们的记录根本不会显示 - 因为在DEPENDENT表中没有匹配的记录。

因此,您使用 left 连接将所有数据保留在“left”(即第一个表)上,并在“right”(第二个表)中提取任何匹配数据:

SELECT EMPLOYEE.FNAME as employee_first, EMPLOYEE.LNAME as employee_last, DEPENDENT.FNAME as dependent_first, DEPENDENT.LNAME as dependent_last
FROM
EMPLOYEE LEFT JOIN DEPENDENT ON EMPLOYEE.SSN=DEPENDENT.ESSN

现在我们获得所有的员工记录。如果给定员工没有匹配的从属项,则dependent_firstdependent_last字段将为空。

答案 1 :(得分:25)

示例(不使用您的示例表: - )

我有一家汽车租赁公司。

Table car
id: integer primary key autoincrement
licence_plate: varchar
purchase_date: date

Table customer
id: integer primary key autoincrement
name: varchar

Table rental
id: integer primary key autoincrement
car_id: integer
bike_id: integer
customer_id: integer
rental_date: date

简单吧?我有10条车的记录,因为我有10辆车 我已经经营这家公司10年了,所以我有1000个客户 而且每辆车每年租车约20倍= 10年x 10辆车x 20 = 2000辆。

如果我把所有东西存放在一张大桌子里,我就有10x1000x2000 = 2000万条记录 如果我将它存储在3个表中,我有10 + 1000 + 2000 = 3010个记录 这是3个数量级,所以这就是我使用3个表的原因。

但是因为我使用3个表(以节省空间和时间)我必须使用连接才能再次获取数据 (至少如果我想要名字和车牌而不是数字)

使用内部联接

客户345的所有租赁?

SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
WHERE customer.id = 345.

这是INNER JOIN,因为我们想要了解实际发生的汽车linked to出租linked to客户。

请注意,我们还有一个bike_id,链接到自行车桌,非常类似于汽车桌,但不同。 我们如何为客户345提供所有自行车+汽车租赁服务 我们可以尝试并执行此操作

SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id)
INNER JOIN car on (car.id = rental.car_id)
INNER JOIN bike on (bike.id = rental.bike_id)
WHERE customer.id = 345.

但那会给出一个空集!! 这是因为出租可以是自行车租赁或车载租赁,但不能同时出租 非工作inner join查询只会为我们在同一笔交易中出租自行车和汽车的所有租赁提供结果。
我们正在尝试使用布尔OR联接获得布尔AND关系。

使用外部联接

为了解决这个问题,我们需要一个outer join

让我们用left join

来解决它
SELECT * FROM customer
INNER JOIN rental on (rental.customer_id = customer.id) <<-- link always
LEFT JOIN car on (car.id = rental.car_id) <<-- link half of the time
LEFT JOIN bike on (bike.id = rental.bike_id) <<-- link (other) 0.5 of the time.
WHERE customer.id = 345.

以这种方式看待它。 inner joinANDleft joinOR,如下面的伪代码所示:

if a=1 AND a=2 then {this is always false, no result}
if a=1 OR a=2 then  {this might be true or not}

如果您创建表并运行查询,则可以看到结果。

术语

left joinleft outer join相同。 没有额外前缀的joininner join 还有full outer join。在25年的编程中,我从未使用过它。

为何选择左加入

嗯,涉及两张桌子。在我们链接的例子中 客户使用inner join租借,在内部联接中,两个表必须链接,以便left:customer表和right:rental表之间没有区别。

下一个链接是left joinleft:rental之间的right:car。在左侧,所有行必须链接,而右侧则不必。这就是left join

的原因

答案 2 :(得分:2)

当您需要所有来自其中一个连接表的结果时,使用外部联接,无论其他表中是否存在匹配的行。

答案 3 :(得分:0)

我认为问题3(b)令人困惑,因为它的整个前提是错误的:你不必使用外部联接来“解决查询”,例如:考虑一下(按照试卷中的语法风格可能是明智的):

SELECT FNAME, LNAME, DEPENDENT_NAME
  FROM EMPLOYEE, DEPENDENT
 WHERE SSN = ESSN
       AND RELATIONSHIP = 'SPOUSE'
UNION 
SELECT FNAME, LNAME, NULL
  FROM EMPLOYEE
EXCEPT 
SELECT FNAME, LNAME, DEPENDENT_NAME
  FROM EMPLOYEE, DEPENDENT
 WHERE SSN = ESSN
       AND RELATIONSHIP = 'SPOUSE'

答案 4 :(得分:0)

一般情况下: JOIN将两张桌子连接在一起。 当你想要查找&#34;时,请使用INNER JOIN,就像查找任何特定列的详细信息一样。 当你想要&#34;演示&#34;时,请使用OUTER JOIN,比如列出2个表的所有信息。