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

MySQL:通过关联查询获取不在另一表中的记录

没问题,我来帮你搞定这类「查询不在另一张表中记录」的需求!先咱们先把你的四张表结构明确下来,方便后续写SQL的时候对照:

-- categories(分类表)
id | name
------------------
1 | category 1
2 | category 2
3 | category 3
4 | category 4
5 | category 5
6 | category 6

-- countries(国家表)
id | name
------------------
1 | country 1
2 | country 2
3 | country 3
4 | country 4
5 | country 5
6 | country 6

-- users(用户表)
id | name | country_id
-------------------------------
1 | john doe 1 | 1
2 | john doe 2 | 2
3 | john doe 3 | 3
4 | john doe 4 | 4
5 | john doe 5 | 4
6 | john doe 6 | 5

-- users_categories(用户分类关联表)
id | category_id | user_id

下面针对几种常见的「不在另一张表」的查询场景,给出具体的SQL实现和逻辑说明:

场景1:查询没有关联任何分类的用户

也就是找出users表中,从未出现在users_categories关联表中的用户,有三种常用写法:

方法1:LEFT JOIN + IS NULL(直观易懂)

SELECT u.id, u.name, u.country_id
FROM users u
LEFT JOIN users_categories uc ON u.id = uc.user_id
WHERE uc.user_id IS NULL;

逻辑:用左连接把用户和关联表绑定,关联表中没有匹配记录的用户,对应的uc.user_id会是NULL,筛选这些结果就是目标用户。

方法2:NOT EXISTS(大数据量下性能更优)

SELECT u.id, u.name, u.country_id
FROM users u
WHERE NOT EXISTS (
    SELECT 1
    FROM users_categories uc
    WHERE uc.user_id = u.id
);

逻辑:子查询检查当前用户是否在关联表中有记录,NOT EXISTS会直接返回没有匹配的用户。这种写法在数据量大时通常比NOT IN更快,而且不会因为关联表存在NULL值导致异常。

方法3:NOT IN(注意避坑)

SELECT u.id, u.name, u.country_id
FROM users u
WHERE u.id NOT IN (
    SELECT uc.user_id
    FROM users_categories uc
    WHERE uc.user_id IS NOT NULL -- 必须过滤NULL,否则结果为空
);

逻辑:提取关联表中所有用户ID,然后筛选不在这个列表里的用户。注意:如果users_categories的user_id存在NULL,NOT IN会直接返回空结果,所以一定要加WHERE uc.user_id IS NOT NULL。

场景2:查询没有被任何用户关联的分类

和场景1逻辑相反,找出categories表中从未被关联的分类:

-- LEFT JOIN写法
SELECT c.id, c.name
FROM categories c
LEFT JOIN users_categories uc ON c.id = uc.category_id
WHERE uc.category_id IS NULL;

-- NOT EXISTS写法(推荐)
SELECT c.id, c.name
FROM categories c
WHERE NOT EXISTS (
    SELECT 1
    FROM users_categories uc
    WHERE uc.category_id = c.id
);

场景3:查询不在指定国家的用户

比如要找出所有不在「country 4」的用户,或者不在某几个国家列表里的用户:

-- 直接通过country_id筛选
SELECT u.id, u.name, u.country_id
FROM users u
WHERE u.country_id != 4;

-- 筛选不在多个国家的用户(比如country 1和country 2)
SELECT u.id, u.name, u.country_id
FROM users u
WHERE u.country_id NOT IN (1, 2);

-- 关联countries表,通过国家名称筛选
SELECT u.id, u.name, u.country_id, c.name AS country_name
FROM users u
JOIN countries c ON u.country_id = c.id
WHERE c.name != 'country 4';

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:06:34