此外,如何适应左外加入,右外加入和全外加入?
当前回答
下面看两张桌子:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
部門
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
内部加入:
大多数写作只是在 sql 查询中加入,它只返回表之间的匹配记录。
查找所有员工及其部门名称:
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
正如你上面看到的那样,Jose 不是从 EMP 在输出中打印,因为它是 dept_id 6 在部门桌上找不到比赛。
因此,加入或只是加入,只返回匹配行。
左边加入:
这将从左表中返回所有记录,仅从右表中匹配记录。
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
HR 和 R&D 行不从部门桌上打印,因为他们没有在 dept_id 上的 Emp 桌上找到比赛。
因此,LEFT JOIN从左桌返回所有行,仅从右桌匹配行。
您也可以在这里查看Demo。
其他回答
一个内部合并只显示行,如果在合并的另一边(右)有一个匹配记录。
一(左)外部连接显示在左侧的每个记录的行列,即使连接的另一(右)侧没有匹配行列,如果没有匹配行列,对另一(右)侧的列将显示零。
答案在每个人的意义上,所以在结果中。
注意:在 SQLite 中没有 RIGHT OUTER JOIN 或 FULL OUTER JOIN. 而且在 MySQL 中也没有 FULL OUTER JOIN。
我的答案是基于上面的笔记。
如果你有兩個桌子,如下:
--[table1] --[table2]
id | name id | name
---+------- ---+-------
1 | a1 1 | a2
2 | b1 3 | b2
CROSS JOIN / OUTER JOIN : 您可以使用 CROSS JOIN 或仅仅使用,如下:
SELECT * FROM table1, table2
--[OR]
SELECT * FROM table1 CROSS JOIN table2
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
1 | a1 | 3 | b2
2 | b1 | 1 | a2
2 | b1 | 3 | b2
INNER JOIN : 如果您想根据表1.id = 表2.id 等关系添加过滤器,您可以使用 INNER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
--[OR]
SELECT * FROM table1 INNER JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+----+------
1 | a1 | 1 | a2
左 [外] 加入 : 如果您希望在上面的结果中包含一个表中的所有行 - 相同的关系 - 您可以使用左加入: (为右加入,只需更改表的位置)
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
--[OR]
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
--[Results:]
id | name | id | name
---+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
FULL OUTER JOIN : 如果您也希望在您的结果中包含其他表中的所有行,您可以使用 FULL OUTER JOIN:
SELECT * FROM table1, table2 WHERE table1.id = table2.id
UNION ALL
SELECT *, Null, Null FROM table1 WHERE Not table1.id In (SELECT id FROM table2)
UNION ALL
SELECT Null, Null, * FROM table2 WHERE Not table2.id In (SELECT id FROM table1)
--[OR] (recommended for SQLite)
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id
UNION ALL
SELECT * FROM table2 LEFT JOIN table1 ON table2.id = table1.id
WHERE table1.id IS NULL
--[OR]
SELECT * FROM table1 FULL OUTER JOIN table2 On table1.id = table2.id
--[Results:]
id | name | id | name
-----+------+------+------
1 | a1 | 1 | a2
2 | b1 | Null | Null
Null | Null | 3 | b2
好吧,作为你的需要,你选择每一个覆盖你的需要。
内部加入需要附加表中包含相关 ID 的记录。
外部连接将为左侧返回记录,即使没有对右侧的记录。
例如,您有一个订单和一个订单细节表,它们由一个“订单ID”相关。
命令
客戶名稱
命令细节
商品名稱 Qty 價格
请求
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
INNER JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
只会返回订单,该订单还包含在订单详细信息表中的一些东西。
如果您将其更改为向左加入
SELECT Orders.OrderID, Orders.CustomerName
FROM Orders
LEFT JOIN OrderDetails
ON Orders.OrderID = OrderDetails.OrderID
然后它将从订单表中返回记录,即使它们没有订单详细记录。
您可以使用此来查找没有订单详细信息的订单,并通过添加一个在哪里条款,如Where OrderDetails.OrderID IS NULL。
假设你加入没有复制的列,这是一个非常常见的案例:
A 和 B 的内部结合会产生 A 交叉B 的结果,即 Venn 图表交叉的内部部分; A 和 B 的外部结合会产生 A 联盟 B 的结果,即 Venn 图表联盟的外部部分。
例子
假设你有两个表,每个单列,并数据如下:
A B
- -
1 3
2 4
3 5
4 6
内部加入
使用相同的查询中的任何一个内部连接提供两张表的交叉,即它们共通的两行。
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
左边加入
左向外加入将提供A中的所有行,加上B中的任何常见行。
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
向外加入
一个正确的外部加入将给所有行在B,加上任何常见行在A。
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
全外加入
一个完整的外部加入会给你A和B的联盟,即A中的所有行和B中的所有行,如果A中的任何东西没有相应的日期在B,那么B部分是零,反之亦然。
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
下面看两张桌子:
EMP
empid name dept_id salary
1 Rob 1 100
2 Mark 1 300
3 John 2 100
4 Mary 2 300
5 Bill 3 700
6 Jose 6 400
部門
deptid name
1 IT
2 Accounts
3 Security
4 HR
5 R&D
内部加入:
大多数写作只是在 sql 查询中加入,它只返回表之间的匹配记录。
查找所有员工及其部门名称:
Select a.empid, a.name, b.name as dept_name
FROM emp a
JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
正如你上面看到的那样,Jose 不是从 EMP 在输出中打印,因为它是 dept_id 6 在部门桌上找不到比赛。
因此,加入或只是加入,只返回匹配行。
左边加入:
这将从左表中返回所有记录,仅从右表中匹配记录。
Select a.empid, a.name, b.name as dept_name
FROM emp a
LEFT JOIN department b
ON a.dept_id = b.deptid
;
empid name dept_name
1 Rob IT
2 Mark IT
3 John Accounts
4 Mary Accounts
5 Bill Security
6 Jose
HR 和 R&D 行不从部门桌上打印,因为他们没有在 dept_id 上的 Emp 桌上找到比赛。
因此,LEFT JOIN从左桌返回所有行,仅从右桌匹配行。
您也可以在这里查看Demo。
推荐文章
- 选项(RECOMPILE)总是更快;为什么?
- 设置数据库从单用户模式到多用户
- oracle中的RANK()和DENSE_RANK()函数有什么区别?
- 的类型不能用作索引中的键列
- SQL逻辑运算符优先级:And和Or
- 如何检查一个表是否存在于给定的模式中
- 添加一个复合主键
- 如何在SQL Server Management Studio中查看查询历史
- 可以为公共表表达式创建嵌套WITH子句吗?
- 什么时候我需要在Oracle SQL中使用分号vs斜杠?
- SQL Server的NOW()?
- 在SQL中,count(列)和count(*)之间的区别是什么?
- 在SQL Server中截断(不是四舍五入)小数位
- 仅在Datetime列上按日期分组
- PostgreSQL通配符LIKE用于单词列表中的任何一个