SQL Server 2008R2:统计每行中非零非空ID的唯一值数量
实现SQL Server 2008 R2中每行有效唯一ID统计的方案
针对你需要统计tableA每行中排除0或NULL后的唯一ID数量并生成met列的需求,我整理了两个在SQL Server 2008 R2中可行的方案,你可以根据场景选择:
方案一:使用UNPIVOT行转列统计
这个方案通过行转列将多列数据转为行结构,再过滤无效值后统计唯一值数量,适合需要对转换后的数据做更多处理的场景:
SELECT t.golf_id, t.res_id, t.res_id2, t.res_id3, t.res_id4, -- 处理所有值都是0/NULL的情况,默认返回0 COALESCE(u.unique_count, 0) AS met FROM tableA t LEFT JOIN ( SELECT golf_id, COUNT(DISTINCT res_value) AS unique_count FROM tableA -- 将四个res_id列转为行 UNPIVOT ( res_value FOR res_cols IN (res_id, res_id2, res_id3, res_id4) ) up -- 过滤掉NULL和0的无效值 WHERE res_value IS NOT NULL AND res_value <> 0 GROUP BY golf_id ) u ON t.golf_id = u.golf_id;
说明:
UNPIVOT把每行的四个res_id列转换为多行数据,每一行对应一个列的取值;- 过滤掉
NULL和0后,用COUNT(DISTINCT)统计每个golf_id下的唯一有效ID数量; - 通过
LEFT JOIN关联原表,保证原表所有行都能被返回,即使某行全是无效值,met会显示0。
方案二:使用VALUES构造临时表统计
这个方案更简洁,直接在子查询中构造临时行集统计,代码紧凑,适合快速实现需求:
SELECT golf_id, res_id, res_id2, res_id3, res_id4, -- 子查询中统计当前行的有效唯一ID数量 ( SELECT COUNT(DISTINCT val) FROM ( -- 将当前行的四个列转为临时行表 VALUES (res_id), (res_id2), (res_id3), (res_id4) ) AS temp(val) WHERE val IS NOT NULL AND val <> 0 ) AS met FROM tableA;
说明:
- 利用
VALUES子句把当前行的四个res_id列构造为一个包含4行的临时表; - 直接在子查询中过滤无效值并统计唯一值数量,作为当前行的
met值; - 不需要额外的JOIN操作,代码更直观,扩展也方便(如果后续新增列,只需在VALUES里添加对应行即可)。
验证示例数据
用你提供的示例数据测试,两个方案都能得到预期的met值:
- 第一行过滤后仅剩下
2068252,唯一值数量为1; - 第二行过滤后有
2076015和2076016两个唯一值,数量为2; - 其他行的统计结果也完全符合你的预期。
内容的提问来源于stack exchange,提问作者PanosPlat
相关产品推荐
相关产品推荐

