SQL 入门指南:子查询的使用场景与方法

发布于:2025-09-06 ⋅ 阅读:(17) ⋅ 点赞:(0)

在 SQL 查询中,我们经常会遇到需要 “先做一个查询,再用这个结果做另一个查询” 的情况。比如 “找出销售额高于平均值的商品”“查询比部门经理工资高的员工” 等。这时候,子查询就能帮我们把两个查询合并成一个,一步到位地解决问题。今天我们就用 “电商商品销售表” 作为案例,从零开始学习子查询的用法。

我整理好了超全的学习资料,蕴含SQL、Python、Excel、数据库、数据分析等内容

学习资料合集https://www.kdocs.cn/l/cjchDXwklk1B

一、什么是子查询?

简单来说,子查询就是 “嵌套在其他 SQL 语句中的查询语句”。它就像一个 “临时计算器”,先算出一个结果,再把这个结果交给外层的主查询使用。

子查询的基本特点:

  • 必须放在括号()
  • 执行顺序是 “先子查询,后主查询”
  • 可以理解为 “先算内层,再算外层”

准备案例数据:电商商品销售表

为了让大家更好地理解,我们先创建一个全新的 “电商商品销售表”(表名:product_sales),包含商品的基本信息和销售数据。以下是创建表和插入数据的代码,大家可以直接复制运行:

-- 创建商品销售表
CREATE TABLE product_sales (
    product_id INT,  -- 商品ID
    product_name VARCHAR(50),  -- 商品名称
    category VARCHAR(20),  -- 商品类别
    price DECIMAL(10,2),  -- 单价
    monthly_sales INT  -- 月销量
);

-- 插入测试数据
INSERT INTO product_sales VALUES
(1, '无线鼠标', '数码配件', 89.00, 1200),
(2, '机械键盘', '数码配件', 199.00, 850),
(3, '纯棉T恤', '服装', 59.00, 2100),
(4, '牛仔裤', '服装', 129.00, 1500),
(5, '保温杯', '日用品', 79.00, 980),
(6, '笔记本', '日用品', 15.00, 3200);

运行后,我们可以用以下语句查看表中数据:

SELECT * FROM product_sales;

表中数据如下:

product_id product_name category price monthly_sales
1 无线鼠标 数码配件 89.00 1200
2 机械键盘 数码配件 199.00 850
3 纯棉 T 恤 服装 59.00 2100
4 牛仔裤 服装 129.00 1500
5 保温杯 日用品 79.00 980
6 笔记本 日用品 15.00 3200

二、子查询的常见使用场景

子查询不是只有一种用法,根据实际需求不同,主要有以下几种常见场景:

场景 1:在 WHERE 子句中使用子查询(单值匹配)

当我们需要 “根据一个具体数值来筛选数据”,但这个数值需要通过查询获得时,就可以在 WHERE 子句中使用子查询。这种子查询的结果通常是一个单一的值。

例子 1:查询月销量高于平均月销量的商品

步骤分析:

  1. 先计算所有商品的平均月销量(子查询)
  2. 再查询月销量高于这个平均值的商品(主查询)

代码实现:

-- 查询月销量高于平均月销量的商品
SELECT product_name, category, monthly_sales
FROM product_sales
WHERE monthly_sales > (
    -- 子查询:计算所有商品的平均月销量
    SELECT AVG(monthly_sales) FROM product_sales
);

查询结果:

product_name category monthly_sales
纯棉 T 恤 服装 2100
牛仔裤 服装 1500
笔记本 日用品 3200

解释:子查询先算出平均月销量是 (1200+850+2100+1500+980+3200)÷6 = 1638.33,主查询再筛选出月销量大于这个值的商品。

场景 2:在 WHERE 子句中使用子查询(多值匹配)

有时候子查询会返回多个结果,这时我们需要用IN关键字来匹配这些值,而不是用=

例子 2:查询与 “无线鼠标” 同类别且价格更高的商品

步骤分析:

  1. 先查询 “无线鼠标” 所属的类别(子查询,结果是 “数码配件”)
  2. 再查询该类别中价格高于 “无线鼠标” 的商品(主查询)

代码实现:

-- 查询与"无线鼠标"同类别且价格更高的商品
SELECT product_name, category, price
FROM product_sales
WHERE 
    category = (
        -- 子查询1:获取"无线鼠标"的类别
        SELECT category FROM product_sales WHERE product_name = '无线鼠标'
    )
    AND price > (
        -- 子查询2:获取"无线鼠标"的价格
        SELECT price FROM product_sales WHERE product_name = '无线鼠标'
    );

查询结果:

product_name category price
机械键盘 数码配件 199.00

这个例子中我们用了两个子查询,分别获取类别和价格,主查询根据这两个条件进行筛选。

场景 3:在 FROM 子句中使用子查询(临时表)

当我们需要对一个查询的结果再进行查询时,可以把第一个查询作为子查询,放在 FROM 子句中,当作一个临时表来使用。

例子 3:查询各品类中月销量最高的商品

步骤分析:

  1. 先按品类分组,查询每个品类的最高月销量(子查询,作为临时表)
  2. 再关联原表,查询出每个品类中达到最高销量的商品信息(主查询)

代码实现:

-- 查询各品类中月销量最高的商品
SELECT p.product_name, p.category, p.monthly_sales
FROM product_sales p
INNER JOIN (
    -- 子查询:按品类分组,查询每个品类的最高月销量
    SELECT category, MAX(monthly_sales) AS max_sales
    FROM product_sales
    GROUP BY category
) temp ON p.category = temp.category AND p.monthly_sales = temp.max_sales;

查询结果:

product_name category monthly_sales
无线鼠标 数码配件 1200
纯棉 T 恤 服装 2100
笔记本 日用品 3200

注意:子查询作为临时表时,必须给它起一个别名(例子中的temp),否则会报错。

场景 4:使用 EXISTS 子查询(判断存在性)

有时候我们只需要判断是否存在满足条件的记录,不需要具体的数据,这时可以用EXISTS关键字。EXISTS在子查询返回至少一行数据时返回TRUE,否则返回FALSE

例子 4:判断是否存在价格低于 50 元且月销量超过 2000 的商品

代码实现:

-- 判断是否存在价格低于50元且月销量超过2000的商品
SELECT 
    CASE 
        WHEN EXISTS (
            SELECT * 
            FROM product_sales 
            WHERE price < 50 AND monthly_sales > 2000
        ) 
        THEN '存在' 
        ELSE '不存在' 
    END AS result;

查询结果:

result
存在

解释:子查询查询到了 "笔记本"(价格 15 元,月销量 3200)满足条件,所以EXISTS返回TRUE,最终结果为 "存在"。

三、子查询使用注意事项

  1. 子查询的执行顺序:总是先执行子查询,再执行主查询
  2. 子查询的括号:必须用括号()把子查询括起来
  3. 临时表别名:当子查询作为临时表使用时(在 FROM 子句中),必须指定别名
  4. 性能考虑:复杂的子查询可能会影响性能,简单查询建议使用子查询,复杂多表查询可以考虑用 JOIN 替代
  5. 结果类型匹配:子查询的结果类型要与主查询中使用它的位置相匹配

四、练习题

  1. 查询价格高于所属品类平均价格的商品(显示商品名称、品类、价格)
  2. 判断是否存在月销量低于 1000 的 "数码配件" 类商品(返回 "存在" 或 "不存在")

练习题答案

  1. 查询价格高于所属品类平均价格的商品:
SELECT p.product_name, p.category, p.price
FROM product_sales p
WHERE price > (
    SELECT AVG(price) 
    FROM product_sales 
    WHERE category = p.category
);

2.判断是否存在月销量低于 1000 的 "数码配件" 类商品:

SELECT 
    CASE 
        WHEN EXISTS (
            SELECT * 
            FROM product_sales 
            WHERE category = '数码配件' AND monthly_sales < 1000
        ) 
        THEN '存在' 
        ELSE '不存在' 
    END AS result;


网站公告

今日签到

点亮在社区的每一天
去签到