EXISTS 语义在 LINQ 中的实现(Any)

SQL 中的 EXISTS

EXISTS 的作用是:只要子查询能查到至少一条记录,就返回真。外层查询的每一行都会代入子查询中进行判断。

-- 查找有对应班级的学生
SELECT * FROM student s
WHERE EXISTS (
    SELECT * FROM Classx c WHERE c.ID = s.ClassID
)

逐步理解:

学生ClassID子查询 SELECT * FROM Classx WHERE ID = ?结果
张三1能查到 ID=1 的班级显示
李四5能查到 ID=5 的班级显示
周七9查不到 ID=9 的班级不显示

LINQ 中的等效写法

在 LINQ 中,使用 Any()​ 方法实现 EXISTS 语义。Any() 返回 bool,表示序列中是否存在满足条件的元素。

using (var db = new DataClasses1DataContext())
{
    var q = from s in db.Student
            where db.Classx.Any(m => m.ID == s.ClassID)
            select s;

    var res = q.ToList();
}Code language: JavaScript (javascript)

方法语法等效写法:

var res = db.Student
    .Where(s => db.Classx.Any(m => m.ID == s.ClassID))
    .ToList();Code language: JavaScript (javascript)

生成的 SQL

SELECT [t0].[ID], [t0].[Name], [t0].[ClassID], [t0].[AddTime], [t0].[Status]
FROM [dbo].[Student] AS [t0]
WHERE EXISTS (
    SELECT NULL AS [EMPTY]
    FROM [dbo].[Classx] AS [t1]
    WHERE ([t1].[ID]) = [t0].[ClassID]
)Code language: PHP (php)

可以看到,LINQ 的 Any() 直接翻译为 SQL 的 EXISTS 子查询,在数据库端执行,不会全表加载到内存。


Any() 的多种用法

场景写法说明
带条件(等效 EXISTS)db.Classx.Any(m => m.ID == s.ClassID)子查询有匹配则返回 true
无条件(永远为 true)db.Classx.Any()等效 EXISTS (SELECT * FROM Classx),永远返回真
判断集合非空list.Any()不查询数据库,判断内存集合是否有元素
带复杂条件db.Classx.Any(m => m.ID == s.ClassID && m.Name.Contains("实验"))多条件 EXISTS

EXISTS 与 IN 的对比

EXISTS 写法:

SELECT * FROM student s
WHERE EXISTS (SELECT 1 FROM Classx c WHERE c.ID = s.ClassID)

IN 写法:

SELECT * FROM student s
WHERE s.ClassID IN (SELECT ID FROM Classx)Code language: CSS (css)

LINQ 中两种写法对比:

// EXISTS 风格(推荐,可走索引)
var q1 = from s in db.Student
         where db.Classx.Any(m => m.ID == s.ClassID)
         select s;

// IN 风格
var classIds = db.Classx.Select(c => c.ID).ToList();
var q2 = from s in db.Student
         where classIds.Contains(s.ClassID)
         select s;Code language: JavaScript (javascript)
对比项EXISTS (Any)IN (Contains)
SQL 生成EXISTS (...) 子查询IN (...) 或参数列表
性能通常更优,可用索引值多时参数膨胀
写法一步完成需先查 ID 列表
推荐关联判断首选简单值列表判断

发表回复

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