完全外部加入

MySQL 不支援 FULL OUTER JOIN,但有一些方法可以模擬一個。

設定資料

-- ----------------------------
-- Table structure for `owners`
-- ----------------------------
DROP TABLE IF EXISTS `owners`;
CREATE TABLE `owners` (
`owner_id` int(11) NOT NULL AUTO_INCREMENT,
`owner` varchar(30) DEFAULT NULL,
PRIMARY KEY (`owner_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;

-- ----------------------------
-- Records of owners
-- ----------------------------
INSERT INTO `owners` VALUES ('1', 'Ben');
INSERT INTO `owners` VALUES ('2', 'Jim');
INSERT INTO `owners` VALUES ('3', 'Harry');
INSERT INTO `owners` VALUES ('6', 'John');
INSERT INTO `owners` VALUES ('9', 'Ellie');
-- ----------------------------
-- Table structure for `tools`
-- ----------------------------
DROP TABLE IF EXISTS `tools`;
CREATE TABLE `tools` (
`tool_id` int(11) NOT NULL AUTO_INCREMENT,
`tool` varchar(30) DEFAULT NULL,
`owner_id` int(11) DEFAULT NULL,
PRIMARY KEY (`tool_id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1;
-- ----------------------------
-- Records of tools
-- ----------------------------
INSERT INTO `tools` VALUES ('1', 'Hammer', '9');
INSERT INTO `tools` VALUES ('2', 'Pliers', '1');
INSERT INTO `tools` VALUES ('3', 'Knife', '1');
INSERT INTO `tools` VALUES ('4', 'Chisel', '2');
INSERT INTO `tools` VALUES ('5', 'Hacksaw', '1');
INSERT INTO `tools` VALUES ('6', 'Level', null);
INSERT INTO `tools` VALUES ('7', 'Wrench', null);
INSERT INTO `tools` VALUES ('8', 'Tape Measure', '9');
INSERT INTO `tools` VALUES ('9', 'Screwdriver', null);
INSERT INTO `tools` VALUES ('10', 'Clamp', null);

我們想看到什麼?

我們希望獲得一個列表,其中我們看到誰擁有哪些工具,以及哪些工具可能沒有所有者。

查詢

為此,我們可以使用 UNION 組合兩個查詢。在第一個查詢中,我們使用 LEFT JOIN 加入了所有者的工具。這會將我們所有的所有者新增到我們的結果集中,如果他們實際擁有工具並不重要。

在第二個查詢中,我們使用 RIGHT JOIN 將工具加入到所有者中。通過這種方式,我們設法獲取結果集中的所有工具,如果它們不屬於任何人,則其所有者列將只包含 NULL。通過新增由 owners.owner_id IS NULL 過濾的 WHERE 子句,我們將結果定義為第一個查詢尚未返回的資料集,因為我們只查詢右連線表中的資料。

由於我們使用 UNION ALL,第二個查詢的結果集將附加到第一個查詢結果集。

SELECT `owners`.`owner`, tools.tool
FROM `owners`
LEFT JOIN `tools` ON `owners`.`owner_id` = `tools`.`owner_id`
UNION ALL
SELECT `owners`.`owner`, tools.tool
FROM `owners`
RIGHT JOIN `tools` ON `owners`.`owner_id` = `tools`.`owner_id`
WHERE `owners`.`owner_id` IS NULL;

+-------+--------------+
| `owner` | tool         |
+-------+--------------+
| `Ben`   | Pliers       |
| `Ben`   | Knife        |
| `Ben`   | Hacksaw      |
| `Jim`   | Chisel       |
| `Harry` | NULL         |
| `John`  | NULL         |
| `Ellie` | Hammer       |
| `Ellie` | Tape Measure |
| `NULL`  | Level        |
| `NULL`  | Wrench       |
| `NULL`  | Screwdriver  |
| `NULL`  | Clamp        |
+-------+--------------+
12 rows in set (0.00 sec)