SQL 中的各类连接
基础数据查看:
SELECT * FROM Student;
SELECT * FROM Classx;
交叉连接(Cross Join / 笛卡尔积)
两张表的每一行都与另一张表的每一行组合,无约束条件。
-- SQL 写法一:逗号分隔(隐式交叉连接)
SELECT * FROM Student s, Classx c;
-- SQL 写法二:显式 CROSS JOIN
SELECT * FROM Student s CROSS JOIN Classx c;
若 A 表 3 条记录、B 表 4 条记录,结果为 3 × 4 = 12 条。
全连接(内连接 / Inner Join)
条件满足才显示匹配结果:
-- 隐式内连接(逗号 + WHERE)
SELECT * FROM Student s, Classx c WHERE s.ClassID = c.ID;
-- 显式内连接(推荐)
SELECT * FROM Student s
JOIN Classx AS c
ON s.ClassID = c.ID;Code language: PHP (php)
外连接
左外连接(左连接)— 左表所有记录必须出现:
SELECT * FROM Student s
LEFT JOIN Classx AS c
ON s.ClassID = c.ID;Code language: PHP (php)
左表(Student)所有记录都显示,右表(Classx)匹配不到的字段为
NULL。
右外连接(右连接)— 右表所有记录必须出现:
SELECT * FROM Student s
RIGHT JOIN Classx AS c
ON s.ClassID = c.ID;Code language: PHP (php)
自连接
同一张表连接自身,通常用于查找同表中满足特定关系的记录:
SELECT * FROM Student s, Student s2
WHERE s.ID != s2.ID
AND s.Name = '李四'
AND s2.ID > s.ID;Code language: JavaScript (javascript)
LINQ 中的对应实现
交叉连接
LINQ 中没有专门的 Cross Join 关键字,使用双 from 实现:
using (var db = new DataClasses1DataContext())
{
// 交叉连接:Student 每条记录 × Classx 每条记录
var result3 = from s in db.Student
from c in db.Classx
select new { s, c };
var res3 = result3.ToList();
}Code language: JavaScript (javascript)
生成的 SQL:
SELECT [t0].[...], [t1].[...] FROM [Student] AS [t0], [Classx] AS [t1]Code language: CSS (css)
对交叉连接结果进行过滤(等效内连接)
var result3 = from s in db.Student
from c in db.Classx
where s.ClassID == c.ID
select new { s, c };
var res3 = result3.ToList();Code language: JavaScript (javascript)
生成的 SQL 等效于
INNER JOIN:SELECT [t0].[...], [t1].[...] FROM [Student] AS [t0], [Classx] AS [t1] WHERE [t0].[ClassID] = [t1].[ID]Code language: PHP (php)
左连接(左外连接)
var result = from s in db.Student
join c in db.Classx
on s.ClassID equals c.ID into gc
from g in gc.DefaultIfEmpty()
select new { Student = s, Classx = g };
var res = result.ToList();Code language: JavaScript (javascript)
LINQ 中没有右连接,但可以通过调换表顺序实现:
// 右连接等效:调换左右表位置 var rightJoin = from c in db.Classx join s in db.Student on c.ID equals s.ClassID into gs from g in gs.DefaultIfEmpty() select new { Classx = c, Student = g };Code language: JavaScript (javascript)
自连接
using (var db = new DataClasses1DataContext())
{
var result3 = from s in db.Student
from s2 in db.Student
where s.ID != s2.ID
&& s.Name == "李四"
&& s.ID < s2.ID
select new { s };
var res3 = result3.ToList();
}Code language: JavaScript (javascript)
生成的 SQL:
SELECT [t0].[...] FROM [Student] AS [t0], [Student] AS [t1] WHERE [t0].[ID] <> [t1].[ID] AND [t0].[Name] = '李四' AND [t0].[ID] < [t1].[ID]Code language: PHP (php)
各类连接对比汇总
| 连接类型 | SQL 关键字 | LINQ 写法 | 说明 |
|---|---|---|---|
| 交叉连接 | CROSS JOIN / 逗号 | from a in A from b in B | 笛卡尔积,无条件 |
| 内连接 | INNER JOIN / 逗号+WHERE | join b in B on a.Key equals b.Key | 仅匹配行 |
| 左外连接 | LEFT JOIN | join ... into + DefaultIfEmpty() | 左表全保留 |
| 右外连接 | RIGHT JOIN | 调换表顺序 + 左连接写法 | LINQ 无原生右连接 |
| 自连接 | 表自身 JOIN | from a in T from b in T | 同表不同别名 |
Previous: 直接执行 SQL 语句查询
Next: 外连接的两种 LINQ 写法