LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

10类SQL查询语句语法结构模板,覆盖90%SQL查询语句应用场景

admin
2025年8月30日 12:42 本文热度 55

我昨天码的《269条常用SQL查询语句》,有的朋友觉得单单常用SQL查询语句这一块,基础的,咋就有这么多?我4年前SQL入门的时候,刚开始看到老师的PPT是这样的:

SELECT [DISTINCT] [TOP] 字段名
FROM 表名
[WHERE] 条件筛选
[GROUP BY] 分组
[HAVING] 分组筛选
[ORDER BY] 排序

当时我觉得,大数据!原来也没什么吗?后来,有一段时间,我与前面朋友的感觉是一样的。为了破解这一感觉,下面,我们一起来把我昨天码的《269条常用SQL查询语句》缩编成《10类SQL查询语句语法结构模板》,这样,只要记住了这些模板,就知道大部分SQL查询语句了,要直接记忆的SQL查询语句就少了。需要的时候,无论是简单的数据筛选,还是复杂的层级统计,我们都可根据这些模板来写或组合SQL查询语句快速实现功能。(三点说明,敬请谅解:稿子是赶出来的,需说明的SQL细节或冗余没时间备注或优化,有问题,留言区讨论;所有代码块或表格,均可左右滚动;用Markdown码的字,纯文本md文档不提供下载,后面有机会转成PDF提供下载。)

一、基础查询(单表简单查询)

从单个表中查询数据,不涉及复杂逻辑。

-- 基础查询语法
SELECT [DISTINCT | ALL]  -- DISTINCT去重,ALL保留所有(默认)
    列名1 [AS 别名1],  -- 要查询的列,AS可指定别名
    列名2 [AS 别名2],
    ...
    [表达式]  -- 如:计算列:price * 1.1 AS 含税价格
FROM 表名 [AS 表别名]  -- 指定数据来源表,AS可省略
[WHERE 行过滤条件]  -- 可选,筛选符合条件的行(不能用聚合函数)
[ORDER BY 排序列 [ASC | DESC], ...]  -- 可选,按指定列排序(ASC升序,DESC降序)
[LIMIT 行数]  -- 可选,限制返回的行数(部分数据库用TOP、ROWNUM等)

示例:从students表中查询年龄大于18的学生姓名和学号,并按学号升序排列,最多返回10条。

SELECT student_id AS 学号, name AS 姓名 
FROM students 
WHERE age > 18 
ORDER BY student_id ASC 
LIMIT 10;

二、多表连接查询

从多个相关表中联合查询数据,通过连接条件关联表之间的关系。

-- 多表连接查询语法
SELECT 表1.列1, 表2.列2, ...  -- 需指定列所属表(或用别名简化)
FROM 表1 [AS 别名1]
    [INNER | LEFT | RIGHT | FULL] JOIN 表2 [AS 别名2]  -- 连接类型
    ON 连接条件  -- 定义两表的关联关系(如:表1.id = 表2.关联id)
    [JOIN 表3 [AS 别名3] ON 连接条件 ...]  -- 可继续连接更多表
[WHERE 行过滤条件]  -- 筛选连接后的行
[ORDER BY 排序列 ...]  -- 排序结果

连接类型说明

  • INNER JOIN:只保留两表中匹配连接条件的行;
  • LEFT JOIN:保留左表所有行,右表无匹配则补NULL;
  • RIGHT JOIN:保留右表所有行,左表无匹配则补NULL;
  • FULL JOIN:保留两表所有行,无匹配则补NULL(部分数据库不支持)。

示例:查询学生姓名及对应的班级名称(关联students表和classes表)。

SELECT s.name AS 学生姓名, c.class_name AS 班级名称
FROM students AS s
LEFT JOIN classes AS c 
ON s.class_id = c.class_id;  -- 连接条件:学生表的班级id = 班级表的id

三、聚合查询(带GROUP BY)

对数据进行分组统计(如:求和、平均值等),需结合聚合函数(SUM、AVG、COUNT等)。

-- 聚合查询语法
SELECT 
    分组列1 [AS 别名1],  -- 按该列分组(必须出现在GROUP BY中)
    分组列2 [AS 别名2],
    聚合函数(列) [AS 聚合别名]  -- 如:COUNT(*) AS 总数,SUM(score) AS 总分
FROM 表名
[WHERE 行过滤条件]  -- 先筛选行,再分组(不能用聚合函数)
GROUP BY 分组列1, 分组列2, ...  -- 按指定列分组
[HAVING 分组过滤条件]  -- 可选,筛选分组后的结果(可使用聚合函数)
[ORDER BY 排序列 ...]  -- 排序分组结果

示例:统计每个班级的学生人数,只保留人数大于30的班级。

SELECT class_id AS 班级ID, COUNT(*) AS 学生人数
FROM students
WHERE age >= 18  -- 先筛选18岁以上的学生
GROUP BY class_id  -- 按班级分组
HAVING COUNT(*) > 30  -- 筛选人数超30的班级
ORDER BY 学生人数 DESC;

四、窗口函数查询

在“窗口”(一组与当前行相关的行)中执行计算,不改变原表行数,排名、分组内统计等场景常用。

-- 窗口函数查询语法
SELECT 
    普通列,  -- 常规查询列
    窗口函数(列) OVER (  -- 窗口函数+OVER子句定义窗口
        [PARTITION BY 分组列]  -- 可选:按列分组(类似GROUP BY,但不合并行)
        [ORDER BY 排序列 [ASC|DESC]]  -- 可选:组内排序
        [ROWS|RANGE BETWEEN 窗口范围]  -- 可选:定义窗口大小(如:前3行到当前行)
    ) AS 窗口结果别名
FROM 表名
[WHERE 行过滤条件]  -- 筛选行
[其他子句,如:GROUP BY、ORDER BY等]

常用窗口函数

  • 排名函数:RANK()(跳号排名)、DENSE_RANK()(连续排名)、ROW_NUMBER()(行号);
  • 聚合函数:SUM()、AVG()等(在窗口内计算)。

示例:查询每个班级学生的成绩及该班级的平均分(不合并原学生行)。

SELECT 
    student_id AS 学号,
    class_id AS 班级ID,
    score AS 成绩,
    AVG(score) OVER (PARTITION BY class_id) AS 班级平均分  -- 按班级分组计算平均分
FROM scores;

五、子查询(嵌套查询)

将一个查询作为另一个查询的一部分(如:条件、数据源等),用在复杂逻辑拆分。

-- 子查询常见位置示例(以WHERE子句为例)
SELECT 列名 
FROM 表名 
WHERE 列名 运算符 (  -- 子查询作为条件
    SELECT 列名 FROM 子表 WHERE 子查询条件
);

-- 子查询也可作为数据源(FROM子句中)
SELECT t.列名 
FROM (SELECT 列名 FROM 表名 WHERE 条件) AS t  -- 子查询结果作为临时表t
WHERE t.列名 > 100;

示例:查询成绩高于班级平均分的学生(子查询计算平均分)。

SELECT student_id, score
FROM scores s1
WHERE score > (
    SELECT AVG(score) FROM scores s2 WHERE s1.class_id = s2.class_id  -- 子查询:当前学生所在班级的平均分
);

六、联合查询(UNION/UNION ALL)

将多个查询结果集合并为一个结果集,要求各查询的列数、列类型一致。

-- 联合查询语法
查询语句1  -- 第一个查询结果集
[UNION | UNION ALL]  -- 合并方式
查询语句2  -- 第二个查询结果集
[UNION | UNION ALL]
...  -- 可继续合并更多查询结果集
[ORDER BY 排序列 ...]  -- 对合并后的整体结果排序(需写在最后)

合并方式说明

  • UNION:合并结果集并去除重复行(会进行去重操作,效率较低);
  • UNION ALL:直接合并所有行,包括重复行(不进行去重,效率较高)。

示例:查询所有年龄小于18岁的学生和所有年龄大于60岁的教师,合并结果并按姓名排序。

-- 查询学生表中年龄小于18岁的学生
SELECT name AS 姓名, '学生' AS 身份, age AS 年龄 FROM students WHERE age < 18
UNION ALL
-- 查询教师表中年龄大于60岁的教师
SELECT name AS 姓名, '教师' AS 身份, age AS 年龄 FROM teachers WHERE age > 60
ORDER BY 姓名 ASC;  -- 对合并后的结果按姓名升序排列

七、带条件的聚合与行转列查询

在聚合查询中按不同条件分别统计,可在一次查询中同时统计同一分组下不同条件的数据,避免多次查询后手动合并结果,或实现行数据到列数据的转换(如:交叉表),常结合CASE WHEN语句使用。

-- 带条件的聚合查询语法
SELECT 
    分组列,  -- 按该列分组
    -- 按条件统计不同类别的数量/总和等
    SUM(CASE WHEN 条件1 THEN 列名 ELSE 0 END) AS 统计结果1,
    AVG(CASE WHEN 条件2 THEN 列名 ELSE NULL END) AS 统计结果2,
    ...
FROM 表名
GROUP BY 分组列  -- 按指定列分组
[ORDER BY 分组列 ...]

示例:统计每个班级中男生和女生的人数(行转列效果)。

SELECT 
    class_id AS 班级ID,
    -- 统计男生人数:当性别为男时计数1,否则0,再求和
    SUM(CASE WHEN gender = '男' THEN 1 ELSE 0 END) AS 男生人数,
    -- 统计女生人数:当性别为女时计数1,否则0,再求和
    SUM(CASE WHEN gender = '女' THEN 1 ELSE 0 END) AS 女生人数
FROM students
GROUP BY class_id  -- 按班级分组统计
ORDER BY class_id;

八、递归查询(WITH RECURSIVE)

处理具有递归关系的数据(如:树形结构:部门层级、评论回复等),通过递归迭代获取多层关联数据,高效处理层级嵌套数据,无需我们手动多层关联查询。

-- 递归查询语法(以PostgreSQL为例,MySQL 8.0+也支持)
WITH RECURSIVE 递归表名 (列1, 列2, ...) AS (
    -- 1. 初始查询(锚点成员):获取最顶层数据
    SELECT 列1, 列2, ... 
    FROM 表名 
    WHERE 初始条件  -- 如:父节点ID为NULL(顶层节点)
    UNION ALL
    -- 2. 递归查询(递归成员):关联自身获取下一层数据
    SELECT 子表.列1, 子表.列2, ... 
    FROM 表名 AS 子表
    INNER JOIN 递归表名 AS 父表 
    ON 子表.父节点列 = 父表.当前节点列  -- 子节点关联父节点
)
-- 3. 查询递归结果
SELECT * FROM 递归表名 [ORDER BY 排序条件];

示例:查询公司部门的层级结构(departments表含dept_iddept_nameparent_dept_id)。

WITH RECURSIVE dept_hierarchy (dept_id, dept_name, parent_dept_id, level) AS (
    -- 初始查询:获取顶级部门(无父部门,parent_dept_id为NULL),层级设为1
    SELECT dept_id, dept_name, parent_dept_id, 1 AS level
    FROM departments
    WHERE parent_dept_id IS NULL
    UNION ALL
    -- 递归查询:关联子部门,层级+1
    SELECT d.dept_id, d.dept_name, d.parent_dept_id, dh.level + 1 AS level
    FROM departments AS d
    INNER JOIN dept_hierarchy AS dh 
    ON d.parent_dept_id = dh.dept_id  -- 子部门的父ID = 递归表中的部门ID
)
-- 查询所有部门及层级,按层级和部门ID排序
SELECT dept_id, dept_name, parent_dept_id, level
FROM dept_hierarchy
ORDER BY level, dept_id;

九、CTE查询(公用表表达式,WITH子句)

通过WITH子句定义一个临时结果集(CTE),替代子查询或临时表,使查询结构更清晰,尤其适用于需多次复用同一子查询结果的场景,可在后续查询中多次引用,简化复杂查询的逻辑结构。

-- CTE查询语法
WITH cte_name1 (列1, 列2, ...) AS (  -- 定义第一个CTE
    SELECT 列1, 列2, ... FROM 表名 WHERE 条件
),
cte_name2 (列a, 列b, ...) AS (  -- 定义第二个CTE(可多个,用逗号分隔)
    SELECT 列a, 列b, ... FROM cte_name1 WHERE 条件  -- 可引用已定义的CTE
)
-- 主查询:使用CTE
SELECT * FROM cte_name1 
INNER JOIN cte_name2 ON 关联条件;

示例:先筛选出成绩前50%的学生,再统计这些学生的班级分布。

-- 定义CTE:筛选成绩前50%的学生(假设用ROW_NUMBER和总人数计算)
WITH top_half_students AS (
    SELECT 
        student_id, 
        class_id, 
        score,
        -- 计算当前学生在所有学生中的排名(降序)
        ROW_NUMBER() OVER (ORDER BY score DESC) AS score_rank,
        -- 计算学生总人数
        COUNT(*) OVER () AS total_students
    FROM scores
    -- 筛选排名 <= 总人数的50%(即前50%)
    QUALIFY score_rank <= total_students * 0.5  -- QUALIFY用于筛选窗口函数结果(部分数据库支持)
)
-- 主查询:统计前50%学生的班级分布
SELECT class_id AS 班级ID, COUNT(*) AS 前50%学生人数
FROM top_half_students
GROUP BY class_id
ORDER BY 前50%学生人数 DESC;

十、分页查询(LIMIT/OFFSET 或 ROW_NUMBER)

将大量查询结果按页分割,每次只返回指定页的数据(如:网页分页展示),不同数据库语法略有差异。

-- 分页查询语法(MySQL、PostgreSQL等)
SELECT 列名 
FROM 表名 
[WHERE 条件]
ORDER BY 排序列  -- 分页必须排序,否则结果不稳定
LIMIT 每页行数 OFFSET 起始位置;  -- OFFSET:跳过的行数(第一页为0)

-- 分页查询语法(SQL Server,使用OFFSET FETCH)
SELECT 列名 
FROM 表名 
[WHERE 条件]
ORDER BY 排序列
OFFSET 起始位置 ROWS FETCH NEXT 每页行数 ROWS ONLY;

参数说明

  • 每页行数:每次返回的记录数(如:10条/页);
  • 起始位置:从第几条记录开始返回(第一页为0,第二页为“每页行数”,以此类推)。

示例:查询学生表中第3页的数据(每页10条,即返回第21-30条,按学号升序)。

-- MySQL/PostgreSQL写法
SELECT student_id, name, age
FROM students
ORDER BY student_id ASC
LIMIT 10 OFFSET 20;  -- 跳过前20条,返回接下来的10条

-- SQL Server写法
SELECT student_id, name, age
FROM students
ORDER BY student_id ASC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

以上是最通用的10类SQL查询语句语法结构模板,能覆盖90%的SQL查询语句应用场景,不同数据库可能在细节上有差异(如:LIMIT vs TOPQUALIFYFULL JOIN等),我们需结合具体数据库文档调整。在实际应用时,我们肯定会碰到一些复杂的应用场景。这个时候,我们可以将以上10类SQL查询语句语法结构模板按需叠加使用,如:连接解决多表关联,聚合解决分组统计,窗口函数解决行级计算,子查询解决逻辑拆分。如何叠加?可根据业务逻辑的复杂度,可以简单地两种组合,也可以多层嵌套。下面从实际常用的组合逻辑出发,介绍几类典型组合模式:

十一、基础组合(2种结构组合)

1、连接查询 + 聚合查询

场景:多表关联后分组统计,如:查询每个部门的员工人数,关联部门表获取部门名称。

-- 连接员工表和部门表,按部门分组统计人数
SELECT 
    d.dept_id AS 部门ID,
    d.dept_name AS 部门名称,
    COUNT(e.emp_id) AS 员工人数  -- 聚合函数:统计每个部门的员工数
FROM 
    departments AS d  -- 部门表(左表)
LEFT JOIN 
    employees AS e  -- 员工表(右表)
    ON d.dept_id = e.dept_id  -- 连接条件:部门ID关联
GROUP BY 
    d.dept_id, d.dept_name  -- 按部门ID和名称分组(GROUP BY需包含非聚合列)
ORDER BY 
    员工人数 DESC;  -- 按人数降序排列
2、窗口函数 + 子查询

场景:子查询筛选数据后,子查询结果作为窗口函数的数据源,用窗口函数计算,如:先通过子查询筛选近30天数据,再用窗口函数计算每日累计销量。

-- 子查询筛选近30天的订单,外层用窗口函数计算累计销售额
SELECT 
    order_date AS 订单日期,
    daily_sales AS 当日销售额,
    -- 窗口函数:按日期排序,计算从第一天到当前行的累计销售额
    SUM(daily_sales) OVER (ORDER BY order_date) AS 累计销售额
FROM (
    -- 子查询:按日期分组,计算每日销售额(筛选近30天数据)
    SELECT 
        order_date,
        SUM(amount) AS daily_sales  -- 聚合每日销售额
    FROM orders
    WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'  -- 筛选条件:近30天
    GROUP BY order_date
) AS daily_data;  -- 子查询结果作为临时表
3、连接查询 + 子查询

场景:子查询作为连接的数据源,多表关联后查询细节,如:查询每个订单对应的商品类别及该类别当月销量。

-- 连接订单明细表与商品表,同时关联子查询获取商品类别的当月销量
SELECT 
    od.order_id AS 订单ID,
    p.product_name AS 商品名称,
    p.category AS 商品类别,
    od.quantity AS 订单数量,
    monthly_category_sales.类别月销量  -- 子查询提供的类别当月总销量
FROM 
    order_details AS od  -- 订单明细表
INNER JOIN 
    products AS p  -- 商品表
    ON od.product_id = p.product_id  -- 连接条件:商品ID关联
INNER JOIN (
    -- 子查询:按商品类别和月份分组,计算每个类别的当月总销量
    SELECT 
        p2.category AS 类别,
        DATE_FORMAT(od2.order_date, '%Y-%m') AS 月份,  -- 格式化日期为“年-月”
        SUM(od2.quantity) AS 类别月销量  -- 聚合:类别当月总销量
    FROM order_details AS od2
    INNER JOIN products AS p2 ON od2.product_id = p2.product_id
    WHERE DATE_FORMAT(od2.order_date, '%Y-%m') = '2023-10'  -- 限定2023年10月
    GROUP BY p2.category, 月份
) AS monthly_category_sales  -- 类别月销量临时表
-- 连接条件:商品类别一致,且订单日期属于子查询的月份
ON p.category = monthly_category_sales.类别 
   AND DATE_FORMAT(od.order_date, '%Y-%m') = monthly_category_sales.月份
WHERE DATE_FORMAT(od.order_date, '%Y-%m') = '2023-10';  -- 筛选10月订单
4、聚合查询 + 子查询

场景:分组聚合后,用子查询作为筛选条件,如:查询销售额高于全店平均销售额的商品类别。

-- 按商品类别分组统计销售额,筛选出高于全店平均销售额的类别
SELECT 
    p.category AS 商品类别,
    SUM(od.quantity * p.price) AS 类别总销售额  -- 聚合:计算类别总销售额(数量×单价)
FROM 
    products AS p  -- 商品表(含单价)
INNER JOIN 
    order_details AS od  -- 订单明细表(含数量)
    ON p.product_id = od.product_id  -- 连接条件:商品ID关联
GROUP BY 
    p.category  -- 按类别分组
HAVING 
    -- 筛选条件:类别总销售额 > 全店平均类别销售额(子查询计算)
    SUM(od.quantity * p.price) > (
        SELECT AVG(category_sales) 
        FROM (
            -- 子查询2:先计算每个类别的总销售额(用于求平均)
            SELECT SUM(od2.quantity * p2.price) AS category_sales 
            FROM products AS p2
            INNER JOIN order_details AS od2 ON p2.product_id = od2.product_id
            GROUP BY p2.category
        ) AS all_categories  -- 所有类别的销售额临时表
    )
ORDER BY 类别总销售额 DESC;
5、基础查询 + 窗口函数

场景:单表查询中直接使用窗口函数,不涉及多表或复杂聚合,如:查询学生成绩及班级内的排名。

-- 单表查询学生成绩,用窗口函数添加班级内排名
SELECT 
    student_id AS 学号,
    name AS 姓名,
    class_id AS 班级ID,
    score AS 成绩,
    -- 窗口函数1:按班级分组,成绩降序排名(相同成绩排名相同,下一名跳号)
    RANK() OVER (PARTITION BY class_id ORDER BY score DESC) AS 班级排名,
    -- 窗口函数2:按班级分组,计算班级内的成绩平均分(不合并行)
    AVG(score) OVER (PARTITION BY class_id) AS 班级平均分
FROM 
    students  -- 仅涉及学生表(单表)
WHERE 
    subject = '数学'  -- 筛选数学科目成绩
ORDER BY 
    class_id, 班级排名;  -- 按班级和排名排序

十二、多层嵌套组合(3种结构组合)

1、连接查询 + 聚合查询 + 子查询

场景:多表连接后分组,用子查询作为聚合筛选条件,如:查询销量高于同类产品平均销量的商品。

-- 连接产品表和订单明细表,分组统计销量,筛选高于同类平均的商品
SELECT 
    p.product_id AS 商品ID,
    p.product_name AS 商品名称,
    p.category AS 商品类别,
    SUM(od.quantity) AS 总销量  -- 聚合函数:统计商品总销量
FROM 
    products AS p  -- 商品表
INNER JOIN 
    order_details AS od  -- 订单明细表
    ON p.product_id = od.product_id  -- 连接条件:商品ID关联
GROUP BY 
    p.product_id, p.product_name, p.category  -- 按商品分组
HAVING 
    -- 筛选条件:总销量 > 该类别商品的平均销量(子查询计算)
    SUM(od.quantity) > (
        SELECT AVG(category_total) 
        FROM (
            -- 子查询2:按类别分组,计算每个类别的商品销量(用于求平均)
            SELECT SUM(quantity) AS category_total 
            FROM order_details 
            GROUP BY product_id
        ) AS sub
    )
ORDER BY 总销量 DESC;
2、连接查询 + 窗口函数 + 子查询

场景:子查询生成临时数据,连接后用窗口函数排名,如:查询活跃用户的订单金额及用户消费排名。

-- 子查询筛选活跃用户,连接订单表,用窗口函数排名
SELECT 
    u.user_id AS 用户ID,
    u.username AS 用户名,
    o.order_amount AS 订单金额,
    -- 窗口函数:按用户分组,订单金额降序排名(用户内的订单排名)
    RANK() OVER (PARTITION BY u.user_id ORDER BY o.order_amount DESC) AS 用户订单排名
FROM 
    users AS u  -- 用户表
INNER JOIN 
    orders AS o  -- 订单表
    ON u.user_id = o.user_id  -- 连接条件:用户ID关联
INNER JOIN (
    -- 子查询:筛选近90天有3次以上订单的活跃用户
    SELECT user_id 
    FROM orders 
    WHERE order_date >= CURRENT_DATE - INTERVAL '90 days'
    GROUP BY user_id 
    HAVING COUNT(*) >= 3  -- 至少3次订单
) AS active_users  -- 活跃用户临时表
ON u.user_id = active_users.user_id;  -- 关联活跃用户
3、聚合查询 + 窗口函数 + 子查询

场景:先通过子查询筛选数据,再分组聚合统计,最后用窗口函数对聚合结果进行二次计算,如:按地区统计销售额,再对各地区销售额进行全国排名。

-- 子查询筛选有效订单,聚合后用窗口函数排名
SELECT 
    region AS 地区,
    total_sales AS 地区总销售额,
    -- 窗口函数:对所有地区的总销售额进行降序排名(不分组即全局排名)
    RANK() OVER (ORDER BY total_sales DESC) AS 全国销售额排名,
    -- 窗口函数:计算该地区销售额占全国总销售额的比例
    ROUND(total_sales / SUM(total_sales) OVER () * 100, 2) AS 占全国比例(%)
FROM (
    -- 子查询1:按地区分组,聚合计算各地区的总销售额(已筛选有效订单)
    SELECT 
        r.region_name AS region,  -- 地区名称
        SUM(o.order_amount) AS total_sales  -- 聚合函数:统计地区总销售额
    FROM 
        orders AS o  -- 订单表
    INNER JOIN 
        users AS u  -- 用户表(关联地区)
        ON o.user_id = u.user_id
    INNER JOIN 
        regions AS r  -- 地区表
        ON u.region_id = r.region_id
    WHERE 
        o.order_status = 'completed'  -- 筛选已完成的有效订单
        AND o.order_date BETWEEN '2023-01-01' AND '2023-12-31'  -- 限定年度
    GROUP BY 
        r.region_name  -- 按地区分组
) AS region_sales  -- 子查询结果:地区-销售额临时表
ORDER BY 
    全国销售额排名;  -- 按排名升序排列

结构说明
(1)子查询:先筛选有效订单(已完成且在指定年度),关联用户表和地区表,按地区分组计算总销售额,生成临时表region_sales
(2)聚合查询:子查询内部通过SUM()GROUP BY完成地区销售额的聚合统计;
(3)窗口函数:主查询中使用RANK()对所有地区的销售额进行全局排名,使用SUM() OVER ()计算全国总销售额并进一步求占比,实现对聚合结果的二次分析。

该组合适用于“先聚合统计、再全局对比”的场景,我们运用这个组合,既能得到分组数据,又能通过窗口函数在分组间进行横向比较。

十三、多层嵌套组合(3种以上结构)

场景:多层子查询嵌套,或叠加更多结构(如:多层子查询(嵌套子查询)+连接+聚合+窗口函数),如:按地区统计平均消费,再排名。

-- 多层嵌套:子查询筛选+连接+聚合+窗口函数排名
SELECT 
    region AS 地区,
    avg_user_spend AS 地区平均消费,
    -- 窗口函数:按地区平均消费降序排名
    RANK() OVER (ORDER BY avg_user_spend DESC) AS 地区消费排名
FROM (
    -- 子查询1:按地区分组,计算每个地区的用户平均消费
    SELECT 
        r.region,
        AVG(u.total_spend) AS avg_user_spend  -- 聚合:地区平均消费
    FROM 
        regions AS r  -- 地区表
    INNER JOIN 
        users AS u  -- 用户表
        ON r.region_id = u.region_id  -- 连接条件:地区ID关联
    INNER JOIN (
        -- 子查询2:计算每个用户的总消费(近1年)
        SELECT 
            user_id,
            SUM(amount) AS total_spend  -- 聚合:用户总消费
        FROM orders 
        WHERE order_date >= CURRENT_DATE - INTERVAL '1 year'  -- 筛选近1年订单
        GROUP BY user_id
    ) AS user_spend  -- 用户消费临时表
    ON u.user_id = user_spend.user_id  -- 关联用户消费数据
    GROUP BY r.region  -- 按地区分组
) AS region_spend;  -- 地区消费临时表

在实际应用中,只要我们掌握了这些SQL查询语句模板,就能轻松应对基础查询任务,对于复杂的应用场景,我们只需灵活组合不同的SQL查询语句模板,结合具体数据库特性调整细节,也会轻松找到解决这些复杂任务的优化代码方案。


阅读原文:原文链接


该文章在 2025/9/1 11:05:23 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved