何时使用左外连接?

发布于 2024-11-04 20:48:19 字数 468 浏览 0 评论 0原文

我不明白左外连接、右外连接的概念,也不明白为什么我们需要使用连接!我正在努力解决的问题和我正在处理的表格在这里: 链接

问题 3(b)

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

问题 3(c) -

在 SQL 中构造一个命令来解决以下查询,使用 (i) join 方法, (ii) 子查询方法。 [10 分] “查找在该设备上工作超过 20 小时的每个工作人员的身份姓名 计算机化项目”

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

I don't understand the concept of a left outer join, a right outer join, or indeed why we need to use a join at all! The question I am struggling with and the table I am working from is here: Link

Question 3(b)

Construct a command in SQL to solve the following query, explaining why it had to employ the
(outer) join method. [5 Marks]
“Find the name of each staff member and his/her dependent spouse, if any”

Question 3(c) -

Construct a command in SQL to solve the following query, using (i) the join method, and (ii) the
subquery method. [10 Marks]
“Find the identity name of each staff member who has worked more than 20 hours on the
Computerization Project”

Can anyone please explain this to me simply?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

随心而道 2024-11-11 20:48:19

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

在您的示例中,您可以组合 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 表中没有匹配的记录。

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

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 字段将为空。

Joins are used to combine two related tables together.

In your example, you can combine the Employee table and the Department table, like so:

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

This would result in a recordset like:

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

I used an INNER JOIN above. INNER JOINs combine two tables so that only records with matches in both tables are displayed, and they are joined in this case, on the department number (field DNO in Employee, DNUMBER in Department table).

LEFT JOINs allow you to combine two tables when you have records in the first table but might not have records in the second table. For example, let's say you want a list of all the employees, plus any dependents:

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

The problem here is that if an employee doesn't have a dependent, then their record won't show up at all -- because there's no matching record in the DEPENDENT table.

So, you use a left join which keeps all the data on the "left" (i.e. the first table) and pulls in any matching data on the "right" (the second table):

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

Now we get all of the employee records. If there is no matching dependent(s) for a given employee, the dependent_first and dependent_last fields will be null.

暮光沉寂 2024-11-11 20:48:19

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

我有一家汽车租赁公司。

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,因为我们想了解链接到实际发生的租赁链接到客户的汽车。

请注意,我们还有一个 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.

但这会给出一个空集!!
这是因为租赁可以是自行车租赁或汽车租赁,但不能同时是两者。
而无效的内连接查询只会给出我们在同一笔交易中同时出租自行车和汽车的所有租赁的结果。
我们正在尝试使用布尔AND连接来获取和布尔OR关系。

使用外连接

为了解决我们需要一个外部连接

我们用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.

这样看。 内连接是一个AND左连接是一个OR,如以下伪代码所示:

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}

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

术语

左连接左外连接相同。
没有额外前缀的连接内部连接
还有一个完全外部连接。在 25 年的编程生涯中我从未使用过它。

为什么左连接

嗯,涉及到两个表。在我们链接的示例中
通过内部联接从客户到租赁,在内部联接中,两个表必须链接,因此left:customer表和右:租赁表。

下一个链接是 left:rentalright:car 之间的左连接。在左侧,所有行都必须链接,而在右侧则不必链接。这就是为什么它是左连接

example (not using your example tables :-)

I have a car rental company.

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

Simple right? I have 10 records for cars because I have 10 cars.
I've been running this business for 10 years, so I've got 1000 customers.
And I rent the cars about 20x per year per cars = 10 years x 10 cars x 20 = 2000 rentals.

If I store everything in one big table I've got 10x1000x2000 = 20 million records.
If I store it in 3 tables I've got 10+1000+2000 = 3010 records.
That's 3 orders of magnitude, so that's why I use 3 tables.

But because I use 3 tables (to save space and time) I have to use joins in order to get the data out again
(at least if I want names and licence plates instead of numbers).

Using inner joins

All rentals for customer 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.

That's an INNER JOIN, because we only want to know about cars linked to rentals linked to customers that actually happened.

Notice that we also have a bike_id, linking to the bike table, which is pretty similar to the car table but different.
How would we get all bike + car rentals for customer 345.
We can try and do this

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.

But that will give an empty set!!
This is because a rental can either be a bike_rental OR a car_rental, but not both at the same time.
And the non-working inner join query will only give results for all rentals where we rent out both a bike and a car in the same transaction.
We are trying to get and boolean OR relationship using a boolean AND join.

Using outer joins

In order to solve this we need an outer join.

Let's solve it with 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.

Look at it this way. An inner join is an AND and a left join is a OR as in the following pseudocode:

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}

If you create the tables and run the query you can see the result.

on terminology

A left join is the same as a left outer join.
A join with no extra prefixes is an inner join
There's also a full outer join. In 25 years of programming I've never used that.

Why Left join

Well there's two tables involved. In the example we linked
customer to rental with an inner join, in an inner join both tables must link so there is no difference between the left:customer table and the right:rental table.

The next link was a left join between left:rental and right:car. On the left side all rows must link and the right side they don't have to. This is why it's a left join

寄居人 2024-11-11 20:48:19

当您需要一个连接表的所有结果时,可以使用外连接,无论另一个表中是否有匹配的行。

You use outer joins when you need all of the results from one of the join tables, whether there is a matching row in the other table or not.

ゝ偶尔ゞ 2024-11-11 20:48:19

我认为问题 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'

I think Question 3(b) is confusing because its entire premise wrong: you don't have to use an outer join to "solve the query" e.g. consider this (following the style of syntax in the exam paper is probably wise):

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'
烟织青萝梦 2024-11-11 20:48:19

一般来说:
JOIN 将两个表连接在一起。
当您想要“查找”时,例如查找任何特定列的详细信息,请使用 INNER JOIN。
当您想要“演示”时,请使用 OUTER JOIN,例如列出 2 个表的所有信息。

In general:
JOIN joints two tables together.
Use INNER JOIN when you wanna "look up", like look up detailed information of any specific column.
Use OUTER JOIN when you wanna "demonstrate", like list all the info of the 2 tables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文