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

使用正则表达式统计SQL查询中WHERE过滤器的数量

统计SQL查询中有效WHERE过滤器数量的解决方案

核心逻辑

要统计的是WHERE和AND的出现次数,但需排除两种场景:

  • JOIN之后、WHERE之前的AND(这类属于表连接条件,不是顶层过滤条件)
  • CASE WHEN子句内部的AND(这类属于分支判断逻辑,不属于顶层过滤器)

实现步骤(分阶段清理+统计)

纯正则直接匹配容易被嵌套结构干扰,所以分四步处理:

  1. 移除SQL注释:避免注释里的WHERE/AND被误统计
  2. 清除CASE WHEN ... END块:彻底排除分支内的所有关键词
  3. 替换JOIN到WHERE的内容:把这段连接逻辑替换成WHERE,消除其中的AND
  4. 统计剩余的WHERE和AND

Python代码示例

import re

def count_valid_filters(sql):
    # 移除单行注释
    sql = re.sub(r'--.*$', '', sql, flags=re.IGNORECASE | re.MULTILINE)
    # 移除多行注释
    sql = re.sub(r'/\*.*?\*/', '', sql, flags=re.IGNORECASE | re.DOTALL)
    # 去掉CASE WHEN整个块的内容
    sql = re.sub(r'CASE\s+WHEN.*?END', '', sql, flags=re.IGNORECASE | re.DOTALL)
    # 把JOIN到WHERE之间的内容替换成WHERE,消除这段里的AND
    sql = re.sub(r'JOIN.*?WHERE', 'WHERE', sql, flags=re.IGNORECASE | re.DOTALL)
    # 统计所有符合要求的WHERE和AND
    return len(re.findall(r'\b(WHERE|AND)\b', sql, flags=re.IGNORECASE))

# 测试用例(对应返回7的场景)
test_sql = """
SELECT *
FROM orders o
JOIN customers c ON o.customer_id = c.id AND c.country = 'USA'
WHERE o.status = 'shipped'
  AND o.order_date > '2023-01-01'
  AND (o.total > 100 OR o.total < 10)
  AND CASE WHEN o.priority = 'high' THEN o.urgent = true AND o.flag = 1 ELSE o.urgent = false END
  AND o.payment_method = 'credit_card'
  AND o.shipping_method = 'express'
  AND o.is_returnable = true
"""
print(count_valid_filters(test_sql))  # 输出7

PostgreSQL函数实现(直接在数据库中使用)

如果要直接统计PostgreSQL中的查询日志,可以写个PL/pgSQL函数:

CREATE OR REPLACE FUNCTION count_query_filters(p_sql text)
RETURNS integer AS $$
DECLARE
    cleaned_text text;
    match_count integer;
BEGIN
    -- 清理单行注释
    cleaned_text := regexp_replace(p_sql, '--.*$', '', 'gmi');
    -- 清理多行注释
    cleaned_text := regexp_replace(cleaned_text, '/\*.*?\*/', '', 'gms');
    -- 移除CASE WHEN块
    cleaned_text := regexp_replace(cleaned_text, 'CASE\s+WHEN.*?END', '', 'gims');
    -- 替换JOIN到WHERE段,保留WHERE
    cleaned_text := regexp_replace(cleaned_text, 'JOIN.*?WHERE', 'WHERE', 'gims');
    -- 统计匹配的关键词数量
    SELECT array_length(regexp_matches(cleaned_text, '\b(WHERE|AND)\b', 'gim'), 1) INTO match_count;
    RETURN COALESCE(match_count, 0);
END;
$$ LANGUAGE plpgsql;

注意事项

  • 这个方案基于常规SQL格式,对于极端嵌套(比如多层CASE、嵌套JOIN)或者非常规写法(比如关键词大小写混用、换行混乱)可能需要调整正则参数
  • 如果查询中存在子查询,若需求是只统计顶层查询的过滤器,还需要额外添加子查询的排除逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:55:27