经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MS SQL Server » 查看文章
列值中获取第一个非空的值
来源:cnblogs  作者:Insus.NET  时间:2019/5/29 8:49:18  对本文有异议

标题是否符合网友的问题宗旨,另外讨论,暂且如此。想了妥解问题,还得看原讨论题。

这是一个网上的问题如下,

  1. ;with temp as
  2. (
  3. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
  4. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
  5. select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
  6. )select * from temp
  7. --以上原始数据
  8. --以下想要的结果
  9. ;with temp as
  10. (
  11. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,'467769309410' rno union all
  12. --select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
  13. select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
  14. )select * from temp
Source Code

 

下面是Insus.NET实现方法。另创建一张临时表,比网友的数据表添加一个字段ID,删除一些与问题无关的字段。

在MS SQL Server 2017版本中实现。

 

Insus.NET的方法是使用ROW_NUMBERPARTITION时行分组:

先分析一列[sno],看看:

 

  1. ;WITH s AS
  2. (
  3. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[sno]) AS [ROW_NUM],
  4. [id],
  5. [repair_no],
  6. [sno]
  7. FROM #T
  8. WHERE [sno] IS NOT NULL
  9. )
  10. SELECT [ROW_NUM],[id],[repair_no],[sno] FROM s;
Source Code

 

另一列[rno]:

 

  1. ;WITH
  2. r AS
  3. (
  4. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[rno]) AS [ROW_NUM],
  5. [id],
  6. [repair_no],
  7. [rno]
  8. FROM #T
  9. WHERE [rno] IS NOT NULL
  10. )
  11. SELECT [ROW_NUM],[id],[repair_no],[rno] FROM r;
Source Code

 

以上加个ID列,主要是为了让大家看到它的排序,拿到的是第一列非空的值。网友的问题,直接按[repair_no]排序即可。
下面代码是把上面2列合并在一起。

  1. ;WITH s AS
  2. (
  3. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[sno]) AS [ROW_NUM],
  4. [id],
  5. [repair_no],
  6. [sno]
  7. FROM #T
  8. WHERE [sno] IS NOT NULL
  9. ),
  10. r AS
  11. (
  12. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[rno]) AS [ROW_NUM],
  13. [id],
  14. [repair_no],
  15. [rno]
  16. FROM #T
  17. WHERE [rno] IS NOT NULL
  18. )
  19. SELECT s.[repair_no],[sno],[rno] FROM s
  20. INNER JOIN r on (s.[repair_no] = r.[repair_no])
  21. WHERE s.[ROW_NUM] = 1 AND r.ROW_NUM = 1;
Source Code

 

使用色彩来引示可以看到明白:

 

把以上方法去解决网友的问题,却得到另外一个结果:

 

对比一下,原来空值也应该有,就是当一个值都没有时,才用空值填充。

看来得改写一下程序,创建临时表,存储结果。

2个字段分别处理,把结果MERGE来合并至临时表中:

 

  1. CREATE TABLE #ok_result([repair_no] INT,[sno] nvarchar(50),[rno] NVARCHAR(50))
  2. ;with temp as
  3. (
  4. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
  5. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
  6. select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
  7. ),s AS
  8. (
  9. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY repair_no) AS [ROW_NUM],
  10. [repair_no],
  11. [sno]
  12. FROM temp
  13. WHERE [sno] IS NOT NULL
  14. )
  15. MERGE #ok_result AS Target
  16. USING (SELECT [repair_no],[sno] FROM s WHERE [ROW_NUM] = 1) AS Source
  17. ON (Target.[repair_no] = Source.[repair_no])
  18. WHEN MATCHED THEN
  19. UPDATE SET target.[sno] = source.[sno]
  20. WHEN NOT MATCHED BY TARGET THEN
  21. INSERT ([repair_no],[sno]) VALUES ([repair_no],[sno]);
  22. ;with temp as
  23. (
  24. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
  25. select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
  26. select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
  27. ),r AS
  28. (
  29. SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY repair_no) AS [ROW_NUM],
  30. [repair_no],
  31. [rno]
  32. FROM temp
  33. WHERE [rno] IS NOT NULL
  34. )
  35. MERGE #ok_result AS Target
  36. USING (SELECT [repair_no],[rno] FROM r WHERE [ROW_NUM] = 1) AS Source
  37. ON (Target.[repair_no] = Source.[repair_no])
  38. WHEN MATCHED THEN
  39. UPDATE SET target.[rno] = source.[rno]
  40. WHEN NOT MATCHED BY TARGET THEN
  41. INSERT ([repair_no],[sno]) VALUES ([repair_no],[rno]);
  42. SELECT [repair_no],[sno],[rno] FROM #ok_result
Source Code

 

原文链接:http://www.cnblogs.com/insus/p/10934929.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号