Skip to content

sql-right-joins

A RIGHT JOIN(或 RIGHT OUTER JOIN)是一种外连接,它返回右表(table2)中的所有行,以及左表(table1)中匹配的行。如果右表中的某一行在左表中没有匹配的行,则结果中左表的所有列将包含 NULL 值。

从视觉上,你可以将 RIGHT JOIN 理解为获取右表中的每一行,然后尝试根据连接条件在左表中查找匹配项。

要点:右表中的所有行都将包含在结果中,无论它们在左表中是否有匹配项。

SELECT
table1.column_name,
table2.column_name
FROM
table1
RIGHT JOIN table2 ON table1.common_field = table2.common_field;

注意:RIGHT JOIN 和 RIGHT OUTER JOIN 在所有主要的 SQL 方言中功能相同。

让我们考虑两个表:CUSTOMERS 和 ORDERS。

CREATE TABLE CUSTOMERS (
ID INT PRIMARY KEY,
NAME VARCHAR(100) NOT NULL,
AGE INT NOT NULL
);
INSERT INTO CUSTOMERS (ID, NAME, AGE) VALUES
(1, 'Ramesh', 32),
(2, 'Khilan', 25),
(3, 'Kaushik', 23),
(4, 'Chaitali', 25);
CREATE TABLE ORDERS (
OID INT PRIMARY KEY,
ORDER_DATE TIMESTAMP NOT NULL,
CUSTOMER_ID INT,
AMOUNT DECIMAL(10, 2)
);
INSERT INTO ORDERS (OID, ORDER_DATE, CUSTOMER_ID, AMOUNT) VALUES
(101, '2023-11-20 10:30:00', 2, 1560.00),
(102, '2023-10-08 14:00:00', 3, 3000.00),
(103, '2023-05-20 18:45:00', 4, 2060.00),
(104, '2023-12-01 09:00:00', 99, 500.00); -- 来自一个不存在客户的订单

请注意,ORDERS 表中有一个 CUSTOMER_ID 为 99 的订单,该客户在 CUSTOMERS 表中不存在。让我们执行一个 RIGHT JOIN 来列出所有订单及其下单客户。

SELECT
c.ID,
c.NAME,
o.OID,
o.AMOUNT
FROM
CUSTOMERS c
RIGHT JOIN ORDERS o ON c.ID = o.CUSTOMER_ID;
IDNAMEOIDAMOUNT
2Khilan1011560.00
3Kaushik1023000.00
4Chaitali1032060.00
NULLNULL104500.00

结果包含了所有四个订单。对于订单 ID 104,客户列(ID、NAME)为 NULL,因为 CUSTOMER_ID 99 在 CUSTOMERS 表中没有匹配项。

专业提示:为了可读性,优先使用 LEFT JOIN

Section titled “专业提示:为了可读性,优先使用 LEFT JOIN”

虽然 RIGHT JOIN 在功能上是有效的,但许多开发人员发现 LEFT JOIN 更直观、更易读,因为我们倾向于从左到右思考。任何 RIGHT JOIN 都可以通过简单地交换表来重写为 LEFT JOIN。

上一个 RIGHT JOIN 等效于以下 LEFT JOIN:

-- 此 LEFT JOIN 会产生完全相同的结果,并且通常更清晰。
SELECT
c.ID,
c.NAME,
o.OID,
o.AMOUNT
FROM
ORDERS o
LEFT JOIN CUSTOMERS c ON o.CUSTOMER_ID = c.ID;

你可以将多个 JOIN 操作链式连接在一起。这些 JOIN 通常从左到右进行评估。让我们添加一个 SALESPERSON 表并将其链接到 ORDERS。

-- 向 ORDERS 表添加 SALESPERSON_ID 列并创建 SALESPERSON 表
ALTER TABLE ORDERS ADD COLUMN SALESPERSON_ID INT;
UPDATE ORDERS SET SALESPERSON_ID = 1 WHERE OID IN (101, 102);
UPDATE ORDERS SET SALESPERSON_ID = 2 WHERE OID IN (103, 104);
CREATE TABLE SALESPERSON (
SID INT PRIMARY KEY,
SNAME VARCHAR(100)
);
INSERT INTO SALESPERSON (SID, SNAME) VALUES (1, 'Sarika'), (2, 'Vivek');
-- 让我们查找所有销售人员以及他们关联的订单
SELECT
s.SNAME AS SalespersonName,
o.OID AS OrderID,
c.NAME AS CustomerName
FROM
CUSTOMERS c
RIGHT JOIN ORDERS o ON c.ID = o.CUSTOMER_ID
RIGHT JOIN SALESPERSON s ON o.SALESPERSON_ID = s.SID;

此查询以 SALESPERSON 作为基表(最终 JOIN 中的最右侧表),确保所有销售人员都被列出。

SalespersonNameOrderIDCustomerName
Sarika101Khilan
Sarika102Kaushik
Vivek103Chaitali
Vivek104NULL

WHERE 子句用于在执行 JOIN 之后 过滤结果。这允许你对连接后的结果集应用条件。

SELECT
c.ID, c.NAME, o.AMOUNT
FROM
CUSTOMERS c
RIGHT JOIN ORDERS o ON c.ID = o.CUSTOMER_ID
WHERE
o.AMOUNT > 2000.00;

这将只返回金额大于 2000.00 的订单,同时仍保持 RIGHT JOIN 逻辑。

IDNAMEAMOUNT
3Kaushik3000.00
4Chaitali2060.00