交叉连接、全连接、外连接与自连接

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 / 逗号+WHEREjoin b in B on a.Key equals b.Key仅匹配行
左外连接LEFT JOINjoin ... into + DefaultIfEmpty()左表全保留
右外连接RIGHT JOIN调换表顺序 + 左连接写法LINQ 无原生右连接
自连接表自身 JOINfrom a in T from b in T同表不同别名

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注