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

如何在SQL中结合使用SUM与MAX函数?附查询需求及问题

解决每个流派筛选消费最高国家记录的SQL问题

问题背景

现有如下SQL查询,用于统计每个流派对应不同国家的交易数据:

SELECT DISTINCT 
    G.NAME AS GENRE, 
    COUNT(T.NAME) AS TotalTransactions, 
    f.country, SUM(il.unitprice) AS Spent
FROM 
    final F
JOIN 
    CUSTOMER C ON C.CUSTOMERID = F.CUSTOMERID
JOIN 
    INVOICE I ON I.CUSTOMERID = C.CUSTOMERID
JOIN 
    INVOICELINE IL ON IL.INVOICEID = I.INVOICEID
JOIN 
    TRACK T ON T.TRACKID = IL.TRACKID
JOIN 
    GENRE G ON G.GENREID = T.GENREID
GROUP BY 
    G.NAME, c.country
ORDER BY 
    G.NAME;

需要进一步筛选出每个流派中消费金额(Spent)最高的国家记录,期望输出示例:

GENRE           TotalTransactions   Country   Spent
 ----------------------------------------------------
 Alternative              5          USA         4.95
 Alternative & Punk      36          Canada     35.64

尝试使用MAX(SUM())时出现分组错误,以下是可行的解决方法:


方法一:使用窗口函数(推荐)

利用ROW_NUMBER()窗口函数,先计算流派-国家的聚合数据,再给每个流派内的记录按消费金额降序排名,取排名第一的记录:

WITH GenreCountryStats AS (
    SELECT 
        G.NAME AS GENRE, 
        COUNT(T.NAME) AS TotalTransactions, 
        C.country, 
        SUM(IL.unitprice) AS Spent
    FROM 
        final F
    JOIN 
        CUSTOMER C ON C.CUSTOMERID = F.CUSTOMERID
    JOIN 
        INVOICE I ON I.CUSTOMERID = C.CUSTOMERID
    JOIN 
        INVOICELINE IL ON IL.INVOICEID = I.INVOICEID
    JOIN 
        TRACK T ON T.TRACKID = IL.TRACKID
    JOIN 
        GENRE G ON G.GENREID = T.GENREID
    GROUP BY 
        G.NAME, C.country
)
SELECT GENRE, TotalTransactions, country, Spent
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY GENRE ORDER BY Spent DESC) AS rn
    FROM GenreCountryStats
) t
WHERE rn = 1
ORDER BY GENRE;
  • 说明:如果有多个国家在同一流派中消费金额并列最高,ROW_NUMBER()会仅保留其中一条;若需保留所有并列记录,可替换为RANK()或DENSE_RANK()。

方法二:子查询关联(兼容旧版数据库)

如果你的数据库不支持窗口函数,可先计算每个流派的最高消费金额,再关联回原始聚合数据:

-- 第一步:计算每个流派-国家的聚合数据
WITH GenreCountryStats AS (
    SELECT 
        G.NAME AS GENRE, 
        COUNT(T.NAME) AS TotalTransactions, 
        C.country, 
        SUM(IL.unitprice) AS Spent
    FROM 
        final F
    JOIN 
        CUSTOMER C ON C.CUSTOMERID = F.CUSTOMERID
    JOIN 
        INVOICE I ON I.CUSTOMERID = C.CUSTOMERID
    JOIN 
        INVOICELINE IL ON IL.INVOICEID = I.INVOICEID
    JOIN 
        TRACK T ON T.TRACKID = IL.TRACKID
    JOIN 
        GENRE G ON G.GENREID = T.GENREID
    GROUP BY 
        G.NAME, C.country
),
-- 第二步:计算每个流派的最高消费金额
GenreMaxSpent AS (
    SELECT 
        GENRE,
        MAX(Spent) AS MaxSpent
    FROM GenreCountryStats
    GROUP BY GENRE
)
-- 第三步:关联筛选出符合条件的记录
SELECT 
    gcs.GENRE, 
    gcs.TotalTransactions, 
    gcs.country, 
    gcs.Spent
FROM GenreCountryStats gcs
JOIN GenreMaxSpent gms ON gcs.GENRE = gms.GENRE AND gcs.Spent = gms.MaxSpent
ORDER BY gcs.GENRE;
  • 说明:该方法会保留同一流派中所有消费金额并列最高的国家记录。

为什么MAX(SUM())会报错?

SQL不允许聚合函数嵌套使用,SUM(il.unitprice)是基于G.NAME, C.country分组后的计算结果,而MAX()需要在更高层级的分组上执行,直接写MAX(SUM(il.unitprice))会导致分组逻辑冲突,因此无法解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:05:25