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

如何用SQL统计跨多文件的名称在最大ID文件及其他文件的出现次数?

问题描述

测试数据

创建测试表及插入数据的SQL如下:

create table tablex (fileID int, file varchar(10), name varchar(10));
insert into tablex (fileID, file, name) values 
(1, 'file1' , 'AAA'),(1, 'file1' , 'AAA'),(1, 'file1' , 'AAA'),
(2, 'file2' , 'AAA'),(2, 'file2' , 'AAA'),(2, 'file2' , 'AAA'),
(1, 'file1' , 'BBB'),(1, 'file1' , 'BBB'),
(2, 'file2' , 'BBB'),(2, 'file2' , 'BBB'),
(3, 'file3' , 'BBB'),(3, 'file3' , 'BBB'),
(1, 'file1' , 'CCC'),(1, 'file1' , 'CCC');

表tablex的数据如下:

fileIDfilename
1file1AAA
1file1AAA
1file1AAA
2file2AAA
2file2AAA
2file2AAA
1file1BBB
1file1BBB
2file2BBB
2file2BBB
3file3BBB
3file3BBB
1file1CCC
1file1CCC

需求说明

仅筛选出出现在多个不同fileID对应文件中的name,然后统计:

  1. 每个name在其所属最大fileID文件中的出现次数
  2. 该name在其他fileID文件中的总出现次数

示例结果:

  • AAA - 在file2中出现3次,在其他文件中出现3次
  • BBB - 在file3中出现2次,在其他文件中出现4次

现有实现

我尝试用窗口函数实现,但需要加distinct才能得到正确结果,不确定这是不是最优方案:

select distinct t.name, 
       count(t.name) over (partition by t.name) countAll,
       count(t.name) over (partition by t.name, fileId) countLatestFile,
       count(t.name) over (partition by t.name) - count(t.name) over (partition by t.name, fileId) countOthers
from tablex t
join (select name from tablex group by name having count(distinct fileId)  > 1) tdups
on t.name = tdups.name;

其他实现思路

思路1:CTE预统计+关联查询

先通过CTE分别统计每个name的总次数、最大fileID,以及各fileID下的出现次数,最后关联计算结果,全程不用窗口函数:

WITH name_stats AS (
    -- 统计每个name的总次数、最大fileID,同时筛选多fileID的name
    SELECT 
        name,
        COUNT(*) AS total_count,
        MAX(fileID) AS max_file_id
    FROM tablex
    GROUP BY name
    HAVING COUNT(DISTINCT fileID) > 1
),
file_name_count AS (
    -- 统计每个name在各fileID下的出现次数
    SELECT 
        name,
        fileID,
        COUNT(*) AS file_count
    FROM tablex
    GROUP BY name, fileID
)
SELECT 
    ns.name,
    fnc.file_count AS max_file_count,
    ns.total_count - fnc.file_count AS other_file_count
FROM name_stats ns
JOIN file_name_count fnc 
    ON ns.name = fnc.name AND ns.max_file_id = fnc.fileID;

思路2:窗口函数标记最大fileID+分组统计

用窗口函数给每个name的最大fileID打标记,之后直接分组计算两类次数:

WITH marked_data AS (
    SELECT 
        name,
        -- 标记当前行是否属于该name的最大fileID
        CASE WHEN fileID = MAX(fileID) OVER (PARTITION BY name) THEN 1 ELSE 0 END AS is_max_file
    FROM tablex
),
filtered_names AS (
    -- 筛选出存在多个fileID的name
    SELECT DISTINCT name
    FROM tablex
    GROUP BY name
    HAVING COUNT(DISTINCT fileID) > 1
)
SELECT 
    md.name,
    SUM(CASE WHEN md.is_max_file = 1 THEN 1 ELSE 0 END) AS max_file_count,
    SUM(CASE WHEN md.is_max_file = 0 THEN 1 ELSE 0 END) AS other_file_count
FROM marked_data md
JOIN filtered_names fn ON md.name = fn.name
GROUP BY md.name;

思路3:子查询嵌套实现

如果数据库不支持CTE,可以用子查询嵌套完成:

SELECT 
    t1.name,
    (SELECT COUNT(*) FROM tablex t2 WHERE t2.name = t1.name AND t2.fileID = t1.max_file_id) AS max_file_count,
    t1.total_count - (SELECT COUNT(*) FROM tablex t2 WHERE t2.name = t1.name AND t2.fileID = t1.max_file_id) AS other_file_count
FROM (
    SELECT 
        name,
        COUNT(*) AS total_count,
        MAX(fileID) AS max_file_id
    FROM tablex
    GROUP BY name
    HAVING COUNT(DISTINCT fileID) > 1
) t1;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 11:58:17