使用正则表达式统计SQL查询中WHERE过滤器的数量
统计SQL查询中有效WHERE过滤器数量的解决方案
核心逻辑
要统计的是WHERE和AND的出现次数,但需排除两种场景:
JOIN之后、WHERE之前的AND(这类属于表连接条件,不是顶层过滤条件)CASE WHEN子句内部的AND(这类属于分支判断逻辑,不属于顶层过滤器)
实现步骤(分阶段清理+统计)
纯正则直接匹配容易被嵌套结构干扰,所以分四步处理:
- 移除SQL注释:避免注释里的
WHERE/AND被误统计 - 清除
CASE WHEN ... END块:彻底排除分支内的所有关键词 - 替换
JOIN到WHERE的内容:把这段连接逻辑替换成WHERE,消除其中的AND - 统计剩余的
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
相关产品推荐
相关产品推荐

