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

如何在PostgreSQL的FILTER子句中使用正则提取函数?

问题:从dept字段括号中提取数据并用于统计列

我需要从dept字段的()中提取数据,以此作为统计列进行数据统计。

基础表结构

----------------------------
| id | active | dept       |
----------------------------
| 1  | true   | TEST (AFG) |
| 2  | true   | TEST (AFG) |
| 3  | true   | TEST (AFG) |
| 4  | true   | TEST (POD) |
| 5  | true   | TEST (POD) |
| 6  | true   | TEST (KMN) |
| 7  | true   | TEST (AGO) |
| 8  | true   | TEST (AGO) |
| 9  | false  | TEST (AGO) |
| 10 | true   | TEST (AGO) |
| 11 | true   | TEST (AGO) |
| 12 | true   | TEST (SUD) |
| 13 | true   | TEST (SUD) |
| 14 | true   | TEST (MOL) |
----------------------------

当前尝试的SQL语句

我原本用来统计活跃/非活跃请求的SQL如下:

SELECT
    'Active Request' AS Title,
    (regexp_matches(dept, '\((.*?)\)'))[1] as dept,
    COUNT(*) FILTER (WHERE dept = 'AFG') AS AFG,
    COUNT(*) FILTER (WHERE dept = 'AGO') AS AGO,
    COUNT(*) FILTER (WHERE dept = 'KMN') AS KMN,
    COUNT(*) FILTER (WHERE dept = 'MOL') AS MOL,
    COUNT(*) FILTER (WHERE dept = 'POD') AS POD,
    COUNT(*) FILTER (WHERE dept = 'SUD') AS SUD,
    COUNT(*) AS TOTAL
FROM req
WHERE active = 'true'
GROUP BY dept
UNION
SELECT
    'Inactive Request' AS Title,
    (regexp_matches(dept, '\((.*?)\)'))[1] as dept,
    COUNT(*) FILTER (WHERE dept = 'AFG') AS AFG,
    COUNT(*) FILTER (WHERE dept = 'AGO') AS AGO,
    COUNT(*) FILTER (WHERE dept = 'KMN') AS KMN,
    COUNT(*) FILTER (WHERE dept = 'MOL') AS MOL,
    COUNT(*) FILTER (WHERE dept = 'POD') AS POD,
    COUNT(*) FILTER (WHERE dept = 'SUD') AS SUD,
    COUNT(*) AS TOTAL
FROM req
WHERE active = 'false'
GROUP BY dept;

遇到的问题

我尝试直接在FILTER子句中使用正则提取函数时,执行以下SQL:

SELECT
    'Active Request' AS Title,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'AFG') AS AFG,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'AGO') AS AGO,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'KMN') AS KMN,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'MOL') AS MOL,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'POD') AS POD,
    COUNT(*) FILTER (WHERE (regexp_matches(dept, '\((.*?)\)'))[1] = 'SUD') AS SUD,
    COUNT(*) AS TOTAL
FROM req
WHERE active = 'true'
GROUP BY dept;

会抛出错误:

Query Error: error: set-returning functions are not allowed in FILTER

目标统计结果

我希望得到如下格式的统计结果:

----------------------------------------------------------------
| Title            | AFG | AGO | KMN | MOL | POD | SUD | TOTAL | 
----------------------------------------------------------------
| Active Request   | 3   | 4   | 1   | 1   | 2   | 2   | 13    |
| Inactive Request | 0   | 1   | 0   | 0   | 0   | 0   | 1     |
----------------------------------------------------------------

目前我可以通过(regexp_matches(dept, '\((.*?)\)'))[1]提取括号中的值,但无法在FILTER子句中直接使用该结果。

解决方案

问题出在regexp_matches是返回集合的函数,不能在FILTER子句中使用。可以改用非集合返回的字符串提取函数,或者先通过CTE/子查询提前提取出部门代码,再进行统计。

方法一:使用substring直接在FILTER中提取

SELECT
    CASE active
        WHEN 'true' THEN 'Active Request'
        ELSE 'Inactive Request'
    END AS Title,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'AFG') AS AFG,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'AGO') AS AGO,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'KMN') AS KMN,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'MOL') AS MOL,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'POD') AS POD,
    COUNT(*) FILTER (WHERE substring(dept from '\((.*?)\)') = 'SUD') AS SUD,
    COUNT(*) AS TOTAL
FROM req
GROUP BY active
ORDER BY Title DESC;

方法二:用CTE提前提取部门代码(更清晰)

WITH req_with_dept_code AS (
    SELECT
        active,
        substring(dept from '\((.*?)\)') AS dept_code
    FROM req
)
SELECT
    CASE active
        WHEN 'true' THEN 'Active Request'
        ELSE 'Inactive Request'
    END AS Title,
    COUNT(*) FILTER (WHERE dept_code = 'AFG') AS AFG,
    COUNT(*) FILTER (WHERE dept_code = 'AGO') AS AGO,
    COUNT(*) FILTER (WHERE dept_code = 'KMN') AS KMN,
    COUNT(*) FILTER (WHERE dept_code = 'MOL') AS MOL,
    COUNT(*) FILTER (WHERE dept_code = 'POD') AS POD,
    COUNT(*) FILTER (WHERE dept_code = 'SUD') AS SUD,
    COUNT(*) AS TOTAL
FROM req_with_dept_code
GROUP BY active
ORDER BY Title DESC;

这两种方法都能避免集合返回函数的问题,直接得到你想要的统计结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:20:30