将yrstphn表指定重复字段值置为null的SQL/游标实现问询
实现建议:用SQL窗口函数高效解决
嘿,这个需求其实用纯SQL就能搞定,而且比游标高效得多——毕竟数据库天生擅长处理集合操作,没必要用逐行遍历的游标。我给你两种方案,优先推荐第一种:
方案一:窗口函数+CASE表达式(推荐)
这个方法利用ROW_NUMBER()窗口函数控制yr列的显示,再用CASE表达式匹配每个st对应的目标phn值:
SELECT -- 只有第一行显示yr,其余行置为null CASE WHEN ROW_NUMBER() OVER (ORDER BY st) = 1 THEN yr ELSE NULL END AS yr, st, -- 根据st匹配对应的phn值 CASE st WHEN 'NV' THEN '1234' WHEN 'MD' THEN '2361' WHEN 'MA' THEN NULL END AS phn FROM ( -- 先去重,得到每个st对应的唯一yr(你的数据里yr都是2012,所以去重后每个st一行) SELECT DISTINCT st, yr FROM yrstphn ) t ORDER BY st;
运行结果
正好就是你想要的输出:
| yr | st | phn |
|---|---|---|
| 2012 | NV | 1234 |
| null | MD | 2361 |
| null | MA | null |
方案二:游标实现(不推荐,仅作参考)
如果因为特殊场景必须用游标,思路是按st排序后逐行遍历,记录是否是第一行来控制yr的输出,同时给每个st赋值对应的phn:
DECLARE @yr INT, @st VARCHAR(2), @phn VARCHAR(4), @is_first_row BIT = 1; -- 声明游标,按st排序 DECLARE cur CURSOR FOR SELECT DISTINCT yr, st FROM yrstphn ORDER BY st; OPEN cur; -- 创建临时表存储结果 CREATE TABLE #temp_result (yr INT, st VARCHAR(2), phn VARCHAR(4)); FETCH NEXT FROM cur INTO @yr, @st; WHILE @@FETCH_STATUS = 0 BEGIN -- 给phn赋值 SET @phn = CASE @st WHEN 'NV' THEN '1234' WHEN 'MD' THEN '2361' WHEN 'MA' THEN NULL END; -- 第一行保留yr,其余行置为null INSERT INTO #temp_result VALUES (CASE WHEN @is_first_row = 1 THEN @yr ELSE NULL END, @st, @phn); SET @is_first_row = 0; FETCH NEXT FROM cur INTO @yr, @st; END; CLOSE cur; DEALLOCATE cur; -- 查询结果 SELECT * FROM #temp_result; DROP TABLE #temp_result;
为什么不推荐游标?
游标是逐行处理数据,性能远不如集合式的SQL操作,而且代码更繁琐,维护成本高。除非你的业务逻辑有非常特殊的逐行依赖场景,否则优先用方案一。
内容的提问来源于stack exchange,提问作者Jlee
相关产品推荐
相关产品推荐

