多条件连接(复合键 Join)

多条件连接(复合键 Join)

SQL 中的多条件连接

在 SQL 中,ON 子句可以使用 AND 组合多个条件:

SELECT TOP 4 s.ID, s.Name, p.Name AS ProductName, p.Price FROM Student s
INNER JOIN Product AS p
ON s.ID = p.Sid AND s.Name = p.NameCode language: PHP (php)

LINQ 中的多条件连接

LINQ 的 join ... on ... equals ... 语法不支持直接用 && 写多个条件,而是通过创建匿名对象来实现复合键匹配:

using (var db = new DataClasses1DataContext())
{
    int pageSize = 2;
    int pageIndex = 4;

    var query = from s in db.Student
                join p in db.Product
                on new { s.ID, s.Name }
                equals new { ID = p.Sid, p.Name }
                select new { s.ID, s.Name, DName = p.Name, p.Price };

    query = query.OrderByDescending(m => m.Price);
    var page = query.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
}Code language: JavaScript (javascript)

匿名对象匹配规则

两个匿名对象要能匹配,必须满足三个条件:

要求说明示例
字段名称两边匿名对象的属性名必须一致左边是 ID,右边也必须是 ID
字段类型对应属性的类型必须相同s.IDintp.Sid 也必须是 int
字段顺序属性的声明顺序也必须一致先写 ID 再写 Name,两边都要先 IDName
// 正确写法:字段名、类型、顺序都一致
new { s.ID, s.Name }  equals  new { ID = p.Sid, Name = p.Name }

// 错误写法:字段名不一致
new { s.ID, s.Name }  equals  new { Sid = p.Sid, p.Name }  // 编译报错

// 错误写法:顺序不一致
new { s.Name, s.ID }  equals  new { ID = p.Sid, Name = p.Name }  // 编译报错Code language: JavaScript (javascript)

执行逻辑

┌─────────────────────────────────────────────────────────────────┐
│  匿名对象 A: { ID = s.ID, Name = s.Name }                        │
│                         equals                                   │
│  匿名对象 B: { ID = p.Sid, Name = p.Name }                       │
├─────────────────────────────────────────────────────────────────┤
│  等效于 SQL:  ON s.ID = p.Sid AND s.Name = p.Name                │
│  LINQ to SQL 会将其翻译为:                                        │
│  INNER JOIN Product p ON s.ID = p.Sid AND s.Name = p.Name        │
└─────────────────────────────────────────────────────────────────┘

三个及以上条件的连接

var query = from s in db.Student
            join p in db.Product
            on new { s.ID, s.Name, s.ClassID }
            equals new { ID = p.Sid, Name = p.Name, ClassID = p.ClassID }
            select new { s.ID, s.Name, p.Price };Code language: JavaScript (javascript)

关键要点

对比项SQLLINQ
单条件连接ON a.ID = b.IDjoin b in ... on a.ID equals b.ID
多条件连接ON a.ID = b.ID AND a.Name = b.Nameon new { a.ID, a.Name } equals new { ID = b.ID, Name = b.Name }
条件运算符=, AND, OR仅支持 equals,多条件通过匿名对象复合键实现
OR 条件ON a.ID = b.ID OR a.Name = b.NameLINQ join 不支持 OR,需用 where 替代

关于 OR 条件:​ LINQ 的 join ... on ... equals ... 不支持 OR 语义。如果需要 OR 逻辑,应改用交叉连接 + where 过滤:

// 等效 SQL: ON s.ID = p.Sid OR s.Name = p.Name
var query = from s in db.Student
            from p in db.Product
            where s.ID == p.Sid || s.Name == p.Name
            select new { s, p };Code language: JavaScript (javascript)

发表回复

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