You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 5.5:如何在同一Eloquent查询中组合whereIn与whereNotIn?

没问题,这需求用单条SQL就能搞定,还能保证效率,给你两种实用方案,顺便说下优化点:

首先先明确下你给出的表结构(方便大家理解):

-- buildings表(存储所有合法建筑ID)
CREATE TABLE buildings (
  id VARCHAR(10) PRIMARY KEY,
  building_name VARCHAR(50)
);
-- 示例数据
INSERT INTO buildings VALUES ('a1', 'adam'), ('b2', 'barney'), ('c3', 'castor');

-- buildings_built表(存储已建成的建筑ID)
CREATE TABLE buildings_built (
  id INT PRIMARY KEY AUTO_INCREMENT,
  building_id VARCHAR(10)
);
-- 示例数据
INSERT INTO buildings_built VALUES (1, 'a1');

方案1:LEFT JOIN + IS NULL(推荐,大表场景性能更稳定)

这是最常用的高效查询方式,利用左连接保留主表数据,再过滤掉已匹配的记录:

SELECT b.id
FROM buildings b
LEFT JOIN buildings_built bb ON b.id = bb.building_id
WHERE b.id IN ('a1', 'b2', 'c3')
  AND bb.building_id IS NULL;

逻辑说明:

  • 先把buildings表和buildings_built表通过建筑ID关联
  • LEFT JOIN会保留buildings中所有符合IN条件的记录(不管有没有在buildings_built里)
  • 最后筛选出那些在buildings_built中没有匹配项的记录(也就是bb.building_id IS NULL),这些就是你需要新建的建筑ID

方案2:NOT EXISTS子查询(可读性强)

如果你觉得子查询更直观,也可以用这个写法,现代数据库的优化器通常会把它优化成和JOIN差不多的执行计划:

SELECT b.id
FROM buildings b
WHERE b.id IN ('a1', 'b2', 'c3')
  AND NOT EXISTS (
    SELECT 1
    FROM buildings_built bb
    WHERE bb.building_id = b.id
  );

逻辑说明:

  • 先筛选出buildings中在目标数组里的记录
  • 再排除掉那些在buildings_built表中存在的记录

优化建议

为了让查询更快,记得给buildings_built的building_id字段加索引:

CREATE INDEX idx_buildings_built_building_id ON buildings_built(building_id);

(buildings的id已经是主键了,自带索引,不用额外加)

这样不管你的数据量多大,查询效率都会有保障,而且完全满足你的需求:既在目标数组、又在buildings表、且不在buildings_built表的有效建筑ID。

内容的提问来源于stack exchange,提问作者Wonka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:16:01