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

如何在单条SQLite查询中统计匹配多分类的行数?

这确实是个典型的痛点——当分类用空格分隔的字符串存储时,常规的CASE分组只会给每行分配一个分类,完全没法处理一行多分类的场景。我给你两个更简洁且符合DRY原则的解决方案:

方案1:用CTE生成分类列表+左连接统计

先通过CTE(公共表表达式)定义所有需要统计的分类(包括none),再左连接原表进行匹配统计,这样不用重复写一堆UNION:

WITH categories_list AS (
    SELECT 'a' AS cat UNION ALL
    SELECT 'b' AS cat UNION ALL
    SELECT 'c' AS cat UNION ALL
    SELECT 'none' AS cat
)
SELECT 
    cl.cat AS categories,
    COUNT(CASE
        WHEN cl.cat = 'none' THEN t.id  -- 统计空分类的行
        ELSE t.id                      -- 统计匹配到对应分类的行
    END) AS total
FROM categories_list cl
LEFT JOIN test t ON 
    -- 非none分类:匹配包含该分类的行(注意加空格避免部分匹配)
    (cl.cat != 'none' AND ' ' || t.cats || ' ' LIKE '% ' || cl.cat || ' %')
    -- none分类:匹配cats为空或null的行
    OR (cl.cat = 'none' AND (t.cats IS NULL OR t.cats = ''))
GROUP BY cl.cat;

这里加' ' || t.cats || ' '是为了避免类似分类'a'匹配到'aa'的情况,让匹配更精准。

方案2:利用字符串拆分函数(SQLite 3.31.0+适用)

如果你的SQLite版本在3.31.0及以上,可以用STRING_SPLIT函数把分隔的分类拆成单独的行,再统一统计:

WITH split_categories AS (
    -- 拆分非空的分类行
    SELECT 
        id,
        TRIM(value) AS cat
    FROM test
    LEFT JOIN STRING_SPLIT(cats, ' ') ON 1=1
    WHERE TRIM(value) != ''
    
    UNION ALL
    
    -- 单独处理空分类的情况
    SELECT 
        id,
        'none' AS cat
    FROM test
    WHERE cats IS NULL OR cats = ''
)
SELECT 
    cat AS categories,
    COUNT(*) AS total  -- 每个拆分后的行对应一个分类+原行,直接统计即可
FROM split_categories
GROUP BY cat;

这个方案更灵活,后续如果新增分类,只需要确保拆分逻辑正确就行,不用修改分类列表。

两种方案都能得到你想要的结果:每个分类(包括none)的条目数,而且不会出现重复代码的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:23:01