PostgreSQL函数get_fields_not_null_cntJSONB非空字段统计核心用于row_to_json多数据质量筛选在PostgreSQL数据库开发中JSONB类型因其灵活的结构特性被广泛用于存储半结构化数据而row_to_json()函数可将表行数据转换为JSONB对象这一组合在“多条同源数据取质量最佳”场景中极为常用——这也是本文主角get_fields_not_null_cnt函数的核心设计目的。实际业务中我们常遇到同一主体的多条数据如多渠道采集的用户信息、重复录入的业务数据需筛选出“有效字段最多”的一条作为最优数据。get_fields_not_null_cnt函数可精准统计JSONB对象中“有效非空”字段数量排除NULL、纯空白字符结合row_to_json()转换表行数据即可高效实现多数据质量排序与筛选。本文将详细解析该函数的实现逻辑、参数用法并重点拆解其核心使用场景——row_to_json()结合多数据质量筛选帮助开发者快速掌握函数的核心价值与实操技巧。一、函数核心功能概述get_fields_not_null_cnt是基于plpgsql编写的PostgreSQL函数核心定位是为“row_to_json()转换后的多数据质量筛选”提供支撑核心功能是统计JSONB对象中满足以下条件的字段数量为数据质量排序提供量化依据字段值不为NULL字段值去除所有空白字符空格、制表符、换行符等后不为空字符串可手动指定需要排除的字段支持批量排除适配不同场景下的无效字段过滤当JSONB对象为空NULL或空对象{}时返回默认值0避免统计异常确保多数据排序时的兼容性。函数标记为IMMUTABLE不可变函数即输入相同的参数时返回结果始终一致有利于PostgreSQL优化查询性能尤其适合多数据批量统计、排序的高频场景与row_to_json()结合时可大幅提升筛选效率。二、函数完整代码与参数解析2.1 完整函数代码CREATEORREPLACEFUNCTIONget_fields_not_null_cnt(row_json JSONB,VARIADIC exclude_fieldsTEXT[]DEFAULTARRAY[]::TEXT[])RETURNSINTEGERAS$$DECLAREv_non_empty_countINTEGER;BEGIN-- 调试信息打印入参和关键过滤条件-- RAISE NOTICE 调试信息开始 ;-- RAISE NOTICE 输入JSONB对象: %, row_json;-- RAISE NOTICE 排除字段列表: %, exclude_fields;-- RAISE NOTICE JSONB是否为空: %, CASE WHEN row_json IS NULL OR row_json {}::JSONB THEN 是 ELSE 否 END;SELECTCOALESCE(res.cnt,def.cnt)INTOv_non_empty_countFROM(SELECT0ascnt)ASdef-- 默认值表空值时取0LEFTJOIN(SELECTCOUNT(*)AScntFROMJSONB_EACH_TEXT(row_json)ASj(key,value)WHERE(exclude_fieldsISNULLORCARDINALITY(exclude_fields)0ORj.keyALL(exclude_fields))ANDj.valueISNOTNULLANDREGEXP_REPLACE(j.value,\s,,g)ANDrow_jsonISNOTNULLANDrow_json{}::JSONB)ASresONTRUE;-- 调试信息打印最终统计结果-- RAISE NOTICE 有值字段统计结果: %, v_non_empty_count;-- RAISE NOTICE 调试信息结束 ;RETURNv_non_empty_count;END;$$LANGUAGEplpgsql IMMUTABLE;2.2 参数详细解析函数仅包含2个参数设计简洁且贴合核心使用场景row_to_json多数据筛选参数说明如下参数名类型默认值说明row_jsonJSONB无默认值必填需要统计非空字段的JSONB对象核心场景中为row_to_json()转换后的表行数据如row_to_json(user_info)的返回结果exclude_fieldsTEXT[]可变参数ARRAY[]::TEXT[]空数组需要排除的字段列表多数据筛选时可排除无关字段支持批量传入如VARIADIC ARRAY[‘create_time’,‘update_time’]注意exclude_fields使用VARIADIC关键字调用时无需手动构造数组直接传入多个字段名即可适配多数据筛选时“快速排除无关字段”的需求下文核心场景示例会详细演示。三、核心逻辑拆解适配多数据质量筛选场景函数的核心逻辑集中在SELECT语句中通过“默认值表LEFT JOIN统计结果表”的方式实现“空JSONB返回0非空JSONB返回有效字段数”为多数据质量排序提供稳定的量化指标逻辑拆解如下3.1 默认值表def(SELECT 0 as cnt) AS def定义了一个默认值表仅包含一个值为0的字段cnt。其核心作用是当row_to_json()转换后的JSONB对象为空如空表行、全NULL字段行时统计结果表res会返回NULL此时通过COALESCE函数取def.cnt即0作为最终结果确保多数据排序时空数据不会因NULL值导致排序异常。3.2 统计结果表res统计结果表通过子查询实现核心是对row_to_json()转换后的JSONB对象表行数据进行拆解和过滤精准统计有效字段数步骤如下拆解JSONB对象使用JSONB_EACH_TEXT(row_json) AS j(key, value)将row_to_json()转换后的JSONB对象表行键值对拆解为独立的键值对key为表字段名value为字段值均为TEXT类型排除指定字段通过(exclude_fields IS NULL OR CARDINALITY(exclude_fields) 0 OR j.key ALL (exclude_fields))实现排除逻辑——多数据筛选时可排除创建时间、更新时间等无关字段仅统计核心业务字段的有效数量过滤无效值j.value IS NOT NULL排除字段值为NULL的情况多数据中NULL字段视为无效数据REGEXP_REPLACE(j.value, \s, , g) 使用正则表达式去除字段值中的所有空白字符\s匹配所有空白‘g’表示全局替换排除纯空白字符串如’ ‘、’\t’等这类数据在多筛选中也视为无效过滤空JSONBrow_json IS NOT NULL AND row_json {}::JSONB确保仅对非空JSONB对象有效表行进行统计避免对空行、无效行的无效计算提升多数据筛选效率。最终子查询通过COUNT(*)统计满足所有条件的字段数量作为res.cnt——该数值即为单条数据的“质量量化值”数值越高数据质量越好。3.3 结果赋值与返回使用SELECT COALESCE(res.cnt, def.cnt) INTO v_non_empty_count将统计结果赋值给变量v_non_empty_count其中COALESCE函数的作用是“取第一个非NULL的值”——当res.cnt为NULL即JSONB为空时取def.cnt0否则取res.cnt有效字段数。最后通过RETURN语句返回统计结果为多数据质量排序提供直接依据。四、核心使用场景row_to_json()结合多数据取质量最佳这是get_fields_not_null_cnt函数的核心设计场景——实际业务中同一主体如同一用户、同一商品可能存在多条同源数据多渠道采集、重复录入等需筛选出“有效字段最多、质量最佳”的一条数据。通过row_to_json()将表行数据转换为JSONB对象再用本函数统计有效字段数即可快速实现质量排序与最优数据筛选。以下通过2个高频实际场景演示函数与row_to_json()的结合用法覆盖单主体多数据筛选、批量多主体筛选贴合真实业务需求。场景1单主体多数据筛选质量最佳一条假设存在用户信息采集表user_collect存储同一用户user_id的多条采集数据需筛选出该用户有效字段最多的一条数据排除create_time、collect_channel等无关字段。-- 1. 创建测试表模拟多渠道采集的用户数据CREATETABLEuser_collect(idSERIALPRIMARYKEY,user_idINT,-- 同一用户标识nameTEXT,-- 核心字段ageTEXT,-- 核心字段emailTEXT,-- 核心字段addressTEXT,-- 核心字段create_timeTIMESTAMPDEFAULTNOW(),-- 无关字段需排除collect_channelVARCHAR(50)-- 无关字段需排除);-- 2. 插入测试数据同一用户user_id1的3条采集数据质量不同INSERTINTOuser_collect(user_id,name,age,email,address,collect_channel)VALUES(1,张三,25,zhangsanexample.com,北京市海淀区,渠道A),-- 4个有效字段(1,张三,NULL,zhangsanexample.com,,渠道B),-- 2个有效字段age NULL、address空(1, ,25,,NULL,渠道C);-- 1个有效字段仅age有效-- 3. 结合row_to_json()筛选质量最佳数据-- 步骤将表行转换为JSONB → 统计有效字段数排除无关字段→ 按有效字段数降序 → 取第一条SELECT-- 将表行数据转换为JSONB对象包含所有字段row_to_json(uc)::jsonbASuser_json,-- 统计有效字段数排除create_time、collect_channel两个无关字段get_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)ASvalid_field_cnt,uc.*FROMuser_collect ucWHEREuc.user_id1-- 筛选同一用户ORDERBYvalid_field_cntDESC,create_timeASC-- 按有效字段数降序相同则取最早采集的LIMIT1;-- 取质量最佳的一条-- 执行结果核心信息-- valid_field_cnt | name | age | email | address-- ----------------|-------|-----|------------------------|------------------ 4 | 张三 | 25 | zhangsanexample.com | 北京市海淀区-- 解析渠道A的数据有效字段最多4个被筛选为最优结果场景2批量多主体各筛选一条质量最佳数据延续场景1的表结构需对所有用户多个user_id各筛选出一条质量最佳的数据适合批量数据清洗、去重场景。-- 插入更多测试数据新增user_id2的2条数据INSERTINTOuser_collect(user_id,name,age,email,address,collect_channel)VALUES(2,李四,NULL,lisiexample.com,上海市浦东新区,渠道A),-- 3个有效字段(2,李四,30,,上海市浦东新区,渠道B);-- 3个有效字段email空-- 批量筛选每个用户取质量最佳数据相同有效字段数取最早采集的WITHuser_qualityAS(SELECTuc.*,-- 统计有效字段数排除无关字段get_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)ASvalid_field_cnt,-- 按用户分组按有效字段数降序、创建时间升序排序给每条数据标序号ROW_NUMBER()OVER(PARTITIONBYuc.user_idORDERBYget_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)DESC,uc.create_timeASC)ASrnFROMuser_collect uc)-- 取每个用户序号为1的数据质量最佳SELECT*FROMuser_qualityWHERErn1;-- 执行结果核心信息-- user_id | name | age | email | address | valid_field_cnt-- --------|-------|-----|------------------------|----------------------|------------------ 1 | 张三 | 25 | zhangsanexample.com | 北京市海淀区 | 4-- 2 | 李四 | NULL| lisiexample.com | 上海市浦东新区 | 3-- 解析user_id1取有效字段4条的记录user_id2取有效字段3条且最早采集的记录补充场景基础调用与空数据处理辅助理解核心场景以下基础调用示例帮助理解函数的基础用法更好适配核心场景中的细节处理示例1基础调用无排除字段-- 测试row_to_json转换后的JSONB对象模拟表行数据SELECTget_fields_not_null_cnt(row_to_json(ROW(张三,25,, ))::JSONB);-- 返回结果2-- 解析转换后的JSONB为{f1:张三,f2:25,f3:,f4: }有效字段为f1、f2示例2排除指定字段核心场景常用-- 排除无关字段f3、f4仅统计核心字段f1、f2SELECTget_fields_not_null_cnt(row_to_json(ROW(张三,25,, ))::JSONB,f3,f4-- 直接传入多个排除字段无需构造数组);-- 返回结果2与示例1一致排除的字段本身为无效字段示例3空数据场景核心场景边界处理-- 场景1row_to_json转换空行无任何有效字段SELECTget_fields_not_null_cnt(row_to_json(ROW(NULL,, ))::JSONB);-- 返回结果0-- 场景2JSONB为空对象表行无任何字段SELECTget_fields_not_null_cnt({}::JSONB);-- 返回结果0五、调试信息说明函数中注释了4行调试信息RAISE NOTICE语句用于开发和测试阶段排查问题——尤其在核心场景中若多数据筛选结果不符合预期可取消注释查看row_to_json()转换后的JSONB对象、排除字段、统计结果等信息快速定位问题。示例调试输出取消注释后结合核心场景NOTICE: 调试信息开始 NOTICE: 输入JSONB对象: {id:1,user_id:1,name:张三,age:25,email:zhangsanexample.com,address:北京市海淀区,create_time:2026-03-16T10:00:00,collect_channel:渠道A} NOTICE: 排除字段列表: {create_time,collect_channel} NOTICE: JSONB是否为空: 否 NOTICE: 有值字段统计结果: 4 NOTICE: 调试信息结束 上线前建议注释调试信息避免不必要的日志输出节省系统资源。六、注意事项与优化建议适配核心场景6.1 注意事项函数仅支持JSONB类型row_to_json()默认返回JSON类型需通过CAST(row_to_json(表名) AS JSONB)转换或直接使用row_to_json(表名)::JSONB核心场景必做步骤正则表达式REGEXP_REPLACE(j.value, \s, , g)会去除所有空白字符若业务需要保留部分空白如“张三 李四”中的空格需修改正则表达式如改为REGEXP_REPLACE(j.value, ^\s|\s$, , g)仅去除首尾空白exclude_fields参数支持“完全匹配”字段名row_to_json()转换后的字段名与表字段名一致若表字段名有大小写差异如userName和username需注意匹配一致性PostgreSQL默认区分大小写核心场景中若表字段较多建议明确指定排除字段避免统计无关字段提升筛选效率和准确性。6.2 优化建议针对多数据筛选场景批量多主体筛选时如场景2可给表的user_id字段添加索引同时给row_to_json()转换后常用的核心字段添加GIN索引提升JSONB拆解和统计效率若频繁使用“固定排除字段”的筛选逻辑可基于本函数封装一个新函数如get_user_valid_cnt预设排除字段简化调用多数据筛选时若有效字段数相同可添加额外排序条件如create_time、collect_channel确保筛选结果唯一、符合业务预期若表数据量极大百万级以上可先通过WHERE条件过滤无效数据如全NULL字段行再进行row_to_json()转换和统计减少计算量。七、总结get_fields_not_null_cnt函数的核心价值的是为“row_to_json()转换后的多数据质量筛选”提供精准的量化指标——通过统计JSONB对象中的有效非空字段数快速实现同一主体多条数据的质量排序筛选出最优结果这也是该函数的设计初衷。函数逻辑简洁、参数灵活不仅适配核心的多数据筛选场景也可用于单个JSONB对象的有效字段统计结合row_to_json()的表行转换能力可广泛应用于数据清洗、重复数据去重、多渠道数据整合等业务场景。开发者可根据自身业务需求调整排除字段、优化正则表达式进一步适配具体场景提升数据处理效率。
PostgreSQL函数:JSONB非空字段统计
PostgreSQL函数get_fields_not_null_cntJSONB非空字段统计核心用于row_to_json多数据质量筛选在PostgreSQL数据库开发中JSONB类型因其灵活的结构特性被广泛用于存储半结构化数据而row_to_json()函数可将表行数据转换为JSONB对象这一组合在“多条同源数据取质量最佳”场景中极为常用——这也是本文主角get_fields_not_null_cnt函数的核心设计目的。实际业务中我们常遇到同一主体的多条数据如多渠道采集的用户信息、重复录入的业务数据需筛选出“有效字段最多”的一条作为最优数据。get_fields_not_null_cnt函数可精准统计JSONB对象中“有效非空”字段数量排除NULL、纯空白字符结合row_to_json()转换表行数据即可高效实现多数据质量排序与筛选。本文将详细解析该函数的实现逻辑、参数用法并重点拆解其核心使用场景——row_to_json()结合多数据质量筛选帮助开发者快速掌握函数的核心价值与实操技巧。一、函数核心功能概述get_fields_not_null_cnt是基于plpgsql编写的PostgreSQL函数核心定位是为“row_to_json()转换后的多数据质量筛选”提供支撑核心功能是统计JSONB对象中满足以下条件的字段数量为数据质量排序提供量化依据字段值不为NULL字段值去除所有空白字符空格、制表符、换行符等后不为空字符串可手动指定需要排除的字段支持批量排除适配不同场景下的无效字段过滤当JSONB对象为空NULL或空对象{}时返回默认值0避免统计异常确保多数据排序时的兼容性。函数标记为IMMUTABLE不可变函数即输入相同的参数时返回结果始终一致有利于PostgreSQL优化查询性能尤其适合多数据批量统计、排序的高频场景与row_to_json()结合时可大幅提升筛选效率。二、函数完整代码与参数解析2.1 完整函数代码CREATEORREPLACEFUNCTIONget_fields_not_null_cnt(row_json JSONB,VARIADIC exclude_fieldsTEXT[]DEFAULTARRAY[]::TEXT[])RETURNSINTEGERAS$$DECLAREv_non_empty_countINTEGER;BEGIN-- 调试信息打印入参和关键过滤条件-- RAISE NOTICE 调试信息开始 ;-- RAISE NOTICE 输入JSONB对象: %, row_json;-- RAISE NOTICE 排除字段列表: %, exclude_fields;-- RAISE NOTICE JSONB是否为空: %, CASE WHEN row_json IS NULL OR row_json {}::JSONB THEN 是 ELSE 否 END;SELECTCOALESCE(res.cnt,def.cnt)INTOv_non_empty_countFROM(SELECT0ascnt)ASdef-- 默认值表空值时取0LEFTJOIN(SELECTCOUNT(*)AScntFROMJSONB_EACH_TEXT(row_json)ASj(key,value)WHERE(exclude_fieldsISNULLORCARDINALITY(exclude_fields)0ORj.keyALL(exclude_fields))ANDj.valueISNOTNULLANDREGEXP_REPLACE(j.value,\s,,g)ANDrow_jsonISNOTNULLANDrow_json{}::JSONB)ASresONTRUE;-- 调试信息打印最终统计结果-- RAISE NOTICE 有值字段统计结果: %, v_non_empty_count;-- RAISE NOTICE 调试信息结束 ;RETURNv_non_empty_count;END;$$LANGUAGEplpgsql IMMUTABLE;2.2 参数详细解析函数仅包含2个参数设计简洁且贴合核心使用场景row_to_json多数据筛选参数说明如下参数名类型默认值说明row_jsonJSONB无默认值必填需要统计非空字段的JSONB对象核心场景中为row_to_json()转换后的表行数据如row_to_json(user_info)的返回结果exclude_fieldsTEXT[]可变参数ARRAY[]::TEXT[]空数组需要排除的字段列表多数据筛选时可排除无关字段支持批量传入如VARIADIC ARRAY[‘create_time’,‘update_time’]注意exclude_fields使用VARIADIC关键字调用时无需手动构造数组直接传入多个字段名即可适配多数据筛选时“快速排除无关字段”的需求下文核心场景示例会详细演示。三、核心逻辑拆解适配多数据质量筛选场景函数的核心逻辑集中在SELECT语句中通过“默认值表LEFT JOIN统计结果表”的方式实现“空JSONB返回0非空JSONB返回有效字段数”为多数据质量排序提供稳定的量化指标逻辑拆解如下3.1 默认值表def(SELECT 0 as cnt) AS def定义了一个默认值表仅包含一个值为0的字段cnt。其核心作用是当row_to_json()转换后的JSONB对象为空如空表行、全NULL字段行时统计结果表res会返回NULL此时通过COALESCE函数取def.cnt即0作为最终结果确保多数据排序时空数据不会因NULL值导致排序异常。3.2 统计结果表res统计结果表通过子查询实现核心是对row_to_json()转换后的JSONB对象表行数据进行拆解和过滤精准统计有效字段数步骤如下拆解JSONB对象使用JSONB_EACH_TEXT(row_json) AS j(key, value)将row_to_json()转换后的JSONB对象表行键值对拆解为独立的键值对key为表字段名value为字段值均为TEXT类型排除指定字段通过(exclude_fields IS NULL OR CARDINALITY(exclude_fields) 0 OR j.key ALL (exclude_fields))实现排除逻辑——多数据筛选时可排除创建时间、更新时间等无关字段仅统计核心业务字段的有效数量过滤无效值j.value IS NOT NULL排除字段值为NULL的情况多数据中NULL字段视为无效数据REGEXP_REPLACE(j.value, \s, , g) 使用正则表达式去除字段值中的所有空白字符\s匹配所有空白‘g’表示全局替换排除纯空白字符串如’ ‘、’\t’等这类数据在多筛选中也视为无效过滤空JSONBrow_json IS NOT NULL AND row_json {}::JSONB确保仅对非空JSONB对象有效表行进行统计避免对空行、无效行的无效计算提升多数据筛选效率。最终子查询通过COUNT(*)统计满足所有条件的字段数量作为res.cnt——该数值即为单条数据的“质量量化值”数值越高数据质量越好。3.3 结果赋值与返回使用SELECT COALESCE(res.cnt, def.cnt) INTO v_non_empty_count将统计结果赋值给变量v_non_empty_count其中COALESCE函数的作用是“取第一个非NULL的值”——当res.cnt为NULL即JSONB为空时取def.cnt0否则取res.cnt有效字段数。最后通过RETURN语句返回统计结果为多数据质量排序提供直接依据。四、核心使用场景row_to_json()结合多数据取质量最佳这是get_fields_not_null_cnt函数的核心设计场景——实际业务中同一主体如同一用户、同一商品可能存在多条同源数据多渠道采集、重复录入等需筛选出“有效字段最多、质量最佳”的一条数据。通过row_to_json()将表行数据转换为JSONB对象再用本函数统计有效字段数即可快速实现质量排序与最优数据筛选。以下通过2个高频实际场景演示函数与row_to_json()的结合用法覆盖单主体多数据筛选、批量多主体筛选贴合真实业务需求。场景1单主体多数据筛选质量最佳一条假设存在用户信息采集表user_collect存储同一用户user_id的多条采集数据需筛选出该用户有效字段最多的一条数据排除create_time、collect_channel等无关字段。-- 1. 创建测试表模拟多渠道采集的用户数据CREATETABLEuser_collect(idSERIALPRIMARYKEY,user_idINT,-- 同一用户标识nameTEXT,-- 核心字段ageTEXT,-- 核心字段emailTEXT,-- 核心字段addressTEXT,-- 核心字段create_timeTIMESTAMPDEFAULTNOW(),-- 无关字段需排除collect_channelVARCHAR(50)-- 无关字段需排除);-- 2. 插入测试数据同一用户user_id1的3条采集数据质量不同INSERTINTOuser_collect(user_id,name,age,email,address,collect_channel)VALUES(1,张三,25,zhangsanexample.com,北京市海淀区,渠道A),-- 4个有效字段(1,张三,NULL,zhangsanexample.com,,渠道B),-- 2个有效字段age NULL、address空(1, ,25,,NULL,渠道C);-- 1个有效字段仅age有效-- 3. 结合row_to_json()筛选质量最佳数据-- 步骤将表行转换为JSONB → 统计有效字段数排除无关字段→ 按有效字段数降序 → 取第一条SELECT-- 将表行数据转换为JSONB对象包含所有字段row_to_json(uc)::jsonbASuser_json,-- 统计有效字段数排除create_time、collect_channel两个无关字段get_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)ASvalid_field_cnt,uc.*FROMuser_collect ucWHEREuc.user_id1-- 筛选同一用户ORDERBYvalid_field_cntDESC,create_timeASC-- 按有效字段数降序相同则取最早采集的LIMIT1;-- 取质量最佳的一条-- 执行结果核心信息-- valid_field_cnt | name | age | email | address-- ----------------|-------|-----|------------------------|------------------ 4 | 张三 | 25 | zhangsanexample.com | 北京市海淀区-- 解析渠道A的数据有效字段最多4个被筛选为最优结果场景2批量多主体各筛选一条质量最佳数据延续场景1的表结构需对所有用户多个user_id各筛选出一条质量最佳的数据适合批量数据清洗、去重场景。-- 插入更多测试数据新增user_id2的2条数据INSERTINTOuser_collect(user_id,name,age,email,address,collect_channel)VALUES(2,李四,NULL,lisiexample.com,上海市浦东新区,渠道A),-- 3个有效字段(2,李四,30,,上海市浦东新区,渠道B);-- 3个有效字段email空-- 批量筛选每个用户取质量最佳数据相同有效字段数取最早采集的WITHuser_qualityAS(SELECTuc.*,-- 统计有效字段数排除无关字段get_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)ASvalid_field_cnt,-- 按用户分组按有效字段数降序、创建时间升序排序给每条数据标序号ROW_NUMBER()OVER(PARTITIONBYuc.user_idORDERBYget_fields_not_null_cnt(row_to_json(uc)::jsonb,create_time,collect_channel,id,user_id)DESC,uc.create_timeASC)ASrnFROMuser_collect uc)-- 取每个用户序号为1的数据质量最佳SELECT*FROMuser_qualityWHERErn1;-- 执行结果核心信息-- user_id | name | age | email | address | valid_field_cnt-- --------|-------|-----|------------------------|----------------------|------------------ 1 | 张三 | 25 | zhangsanexample.com | 北京市海淀区 | 4-- 2 | 李四 | NULL| lisiexample.com | 上海市浦东新区 | 3-- 解析user_id1取有效字段4条的记录user_id2取有效字段3条且最早采集的记录补充场景基础调用与空数据处理辅助理解核心场景以下基础调用示例帮助理解函数的基础用法更好适配核心场景中的细节处理示例1基础调用无排除字段-- 测试row_to_json转换后的JSONB对象模拟表行数据SELECTget_fields_not_null_cnt(row_to_json(ROW(张三,25,, ))::JSONB);-- 返回结果2-- 解析转换后的JSONB为{f1:张三,f2:25,f3:,f4: }有效字段为f1、f2示例2排除指定字段核心场景常用-- 排除无关字段f3、f4仅统计核心字段f1、f2SELECTget_fields_not_null_cnt(row_to_json(ROW(张三,25,, ))::JSONB,f3,f4-- 直接传入多个排除字段无需构造数组);-- 返回结果2与示例1一致排除的字段本身为无效字段示例3空数据场景核心场景边界处理-- 场景1row_to_json转换空行无任何有效字段SELECTget_fields_not_null_cnt(row_to_json(ROW(NULL,, ))::JSONB);-- 返回结果0-- 场景2JSONB为空对象表行无任何字段SELECTget_fields_not_null_cnt({}::JSONB);-- 返回结果0五、调试信息说明函数中注释了4行调试信息RAISE NOTICE语句用于开发和测试阶段排查问题——尤其在核心场景中若多数据筛选结果不符合预期可取消注释查看row_to_json()转换后的JSONB对象、排除字段、统计结果等信息快速定位问题。示例调试输出取消注释后结合核心场景NOTICE: 调试信息开始 NOTICE: 输入JSONB对象: {id:1,user_id:1,name:张三,age:25,email:zhangsanexample.com,address:北京市海淀区,create_time:2026-03-16T10:00:00,collect_channel:渠道A} NOTICE: 排除字段列表: {create_time,collect_channel} NOTICE: JSONB是否为空: 否 NOTICE: 有值字段统计结果: 4 NOTICE: 调试信息结束 上线前建议注释调试信息避免不必要的日志输出节省系统资源。六、注意事项与优化建议适配核心场景6.1 注意事项函数仅支持JSONB类型row_to_json()默认返回JSON类型需通过CAST(row_to_json(表名) AS JSONB)转换或直接使用row_to_json(表名)::JSONB核心场景必做步骤正则表达式REGEXP_REPLACE(j.value, \s, , g)会去除所有空白字符若业务需要保留部分空白如“张三 李四”中的空格需修改正则表达式如改为REGEXP_REPLACE(j.value, ^\s|\s$, , g)仅去除首尾空白exclude_fields参数支持“完全匹配”字段名row_to_json()转换后的字段名与表字段名一致若表字段名有大小写差异如userName和username需注意匹配一致性PostgreSQL默认区分大小写核心场景中若表字段较多建议明确指定排除字段避免统计无关字段提升筛选效率和准确性。6.2 优化建议针对多数据筛选场景批量多主体筛选时如场景2可给表的user_id字段添加索引同时给row_to_json()转换后常用的核心字段添加GIN索引提升JSONB拆解和统计效率若频繁使用“固定排除字段”的筛选逻辑可基于本函数封装一个新函数如get_user_valid_cnt预设排除字段简化调用多数据筛选时若有效字段数相同可添加额外排序条件如create_time、collect_channel确保筛选结果唯一、符合业务预期若表数据量极大百万级以上可先通过WHERE条件过滤无效数据如全NULL字段行再进行row_to_json()转换和统计减少计算量。七、总结get_fields_not_null_cnt函数的核心价值的是为“row_to_json()转换后的多数据质量筛选”提供精准的量化指标——通过统计JSONB对象中的有效非空字段数快速实现同一主体多条数据的质量排序筛选出最优结果这也是该函数的设计初衷。函数逻辑简洁、参数灵活不仅适配核心的多数据筛选场景也可用于单个JSONB对象的有效字段统计结合row_to_json()的表行转换能力可广泛应用于数据清洗、重复数据去重、多渠道数据整合等业务场景。开发者可根据自身业务需求调整排除字段、优化正则表达式进一步适配具体场景提升数据处理效率。