列值中获取第一个非空的值

栏目: 数据库 · 发布时间: 6年前

内容简介:标题是否符合网友的问题宗旨,另外讨论,暂且如此。想了妥解问题,还得看原讨论题。这是一个网上的问题如下,

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

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

列值中获取第一个非空的值


;with temp as 
(
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
    select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
)select * from temp
--以上原始数据
--以下想要的结果
;with temp as 
(
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,'467769309410' rno union all
    --select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
    select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
)select * from temp

Source Code

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

在MS SQL Server 2017版本中实现。

列值中获取第一个非空的值

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

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

列值中获取第一个非空的值


;WITH s AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[sno]) AS [ROW_NUM],
    [id],
    [repair_no],
    [sno]
    FROM #T
    WHERE [sno] IS NOT NULL
)

SELECT [ROW_NUM],[id],[repair_no],[sno] FROM s;

Source Code

另一列[rno]:

列值中获取第一个非空的值


;WITH
r AS
(
    SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[rno]) AS [ROW_NUM],
    [id],
    [repair_no],
    [rno]
    FROM #T
    WHERE [rno] IS NOT NULL
)
SELECT [ROW_NUM],[id],[repair_no],[rno] FROM r;

Source Code

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

下面代码是把上面2列合并在一起。

列值中获取第一个非空的值


;WITH s AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[sno]) AS [ROW_NUM],
    [id],
    [repair_no],
    [sno]
    FROM #T
    WHERE [sno] IS NOT NULL
),
r AS
(
    SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY [id],[rno]) AS [ROW_NUM],
    [id],
    [repair_no],
    [rno]
    FROM #T
    WHERE [rno] IS NOT NULL
)
SELECT s.[repair_no],[sno],[rno] FROM s
INNER JOIN r  on (s.[repair_no] = r.[repair_no])
WHERE s.[ROW_NUM] = 1 AND r.ROW_NUM = 1;

Source Code

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

列值中获取第一个非空的值

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

列值中获取第一个非空的值

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

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

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

列值中获取第一个非空的值


CREATE TABLE #ok_result([repair_no] INT,[sno] nvarchar(50),[rno] NVARCHAR(50))

;with temp as 
(
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
    select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
),s AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY repair_no) AS [ROW_NUM],    
    [repair_no],
    [sno]
    FROM temp
    WHERE [sno] IS NOT NULL
)
 MERGE #ok_result AS Target
    USING (SELECT [repair_no],[sno] FROM s WHERE [ROW_NUM] = 1) AS Source
    ON (Target.[repair_no] = Source.[repair_no])
 
    WHEN MATCHED THEN
        UPDATE SET target.[sno] = source.[sno]
 
    WHEN NOT MATCHED BY TARGET THEN
        INSERT ([repair_no],[sno]) VALUES ([repair_no],[sno]);  

        
;with temp as 
(
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,null sno,'467769309410' rno union all
    select '63738893' repair_no,'20190504' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno union all
    select '63738793' repair_no,'20190508' report_date,'HES2418819040700003'service_sheet_no,'467769309411' sno,null rno
),r AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY [repair_no] ORDER BY repair_no) AS [ROW_NUM],    
    [repair_no],
    [rno]
    FROM temp
    WHERE [rno] IS NOT NULL
)
 MERGE #ok_result AS Target
    USING (SELECT [repair_no],[rno] FROM r WHERE [ROW_NUM] = 1) AS Source
    ON (Target.[repair_no] = Source.[repair_no])
 
    WHEN MATCHED THEN
        UPDATE SET target.[rno] = source.[rno]
 
    WHEN NOT MATCHED BY TARGET THEN
        INSERT ([repair_no],[sno]) VALUES ([repair_no],[rno]);  



SELECT [repair_no],[sno],[rno] FROM #ok_result

Source Code

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

村落效应

村落效应

[加] 苏珊·平克(Susan Pinker) / 青涂 / 浙江人民出版社 / 2017-3-1 / CNY 69.90

 面对面的接触是作为社会性动物的人类最古老、深刻的需求。在互联网时代,社交媒体已经成为人际沟通的主体,人际关系的维系越来越被社交媒体上的点赞、转发、评论代替,在冰冷的互动中,我们失去了真实与温度。面对面的人际关系与接触能让人感受到如村落生活般的归属感,它是一个人免疫力、复原力和影响力的真正来源。虽然互联网拥有毋庸置疑的优势,但是如果我们渴望快乐、健康、长寿……没错,还有智慧,我们就需要想方设法腾......一起来看看 《村落效应》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器