在 SQL Server 中处理 Null 值和重复记录

Posted

技术标签:

【中文标题】在 SQL Server 中处理 Null 值和重复记录【英文标题】:Treating Null values and duplicate records in SQL Server 【发布时间】:2014-10-01 16:10:45 【问题描述】:

我有一个场景,我正在使用SQL Server Reporting Services 创建一个表格报告,并停留在我得到一列重复值的地方。以下是代码的示例输出:

AppID   EmpID   EmpName
2002912 81555   NULL
2002912 81588   Jenn - 81588
2026880 9328    NULL
2026880 9628    Brad  - 09628
2027065 92174   Julie - 92174
2027065 92714   NULL
2028989 72138   NULL
2028989 91366   Alan - 91366
2029233 17438   NULL
2029233 53712   Brad - 53712
2031585 37902   NULL
2031588 17723   Richard - 17723
2031591 54551   Paula - 54551
2031593 52240   Sarah - 52240
2031597 72778   Daisy - 72778
2031603 12659   NULL

请注意,第一列 (AppID) 几乎没有重复项,并且对应的列 EmpName 要么是 Null,要么具有一些值。我想消除所有重复的AppID's,其中EmpNamenull

如果唯一的AppID 没有空值(请参阅最后一行),这可能是直截了当的,我也无法硬编码,因为我正在处理大量数据。

另外请注意,所有这三列都来自不同的表,并且从 LEFT JOINAppID 表。如果您需要查看代码,请告诉我,我没有将其粘贴在这里,因为它有点复杂,虽然可能不需要。

感谢您的任何帮助和建议。谢谢

【问题讨论】:

使用 ROW_NUMBER OVER (partition by appid ORDER BY EmpName NULLS FIRST) 并选择第 2 行。Im not sure about the syntax,but this is the general idea.OR use ORDER BY (CASE WHEN EmpNAme IS NULL THEN 0 ELSE 1 END)` 如果 NULLS FIRST 不可用。 我不想消除AppID 唯一的null 值。那么在这种情况下,这将如何区分重复的AppID's 和唯一的AppID's 【参考方案1】:

在 CTE 中使用 ROW_NUMBER 函数,然后选择第一行。虽然如果有多个 EmpName 不是 NULL,您将只能按字母顺序获得第一个。

WITH AppAndEmp AS
(
    SELECT
        AppID
        , EmpID
        , EmpName
        , ROW_NUMBER() OVER(PARTITION BY AppId
                       ORDER BY (CASE WHEN EmpName IS NULL THEN 0 ELSE 1 END) DESC
                                , EmpName) AS EmpOrder

    FROM
        dbo.App
        LEFT JOIN dbo.Emp
            ON  App.AppId = Emp.AppId
)

SELECT
    *

FROM
    AppAndEmp

WHERE
    EmpOrder = 1

【讨论】:

您的回答非常好,而且确实有效。我知道我们不应该因为只是说谢谢而发表评论,但我真的无法阻止自己,因为它为我节省了大量时间来获得答案。【参考方案2】:

编辑

@djphatic:感谢您的评论。我更正了我的答案。

-- These are those who have set a EmpName but have an invalid row too
select * from data where AppID in (
    select AppID from data group by AppID having count(AppID) > 1
)
and empname is not null
union
-- These are those who MIGHT have set a EmpName or NULL
select * from data where AppID in (
    select AppID from data group by AppID having count(AppID) = 1
)

=> SQLFiddle


为了失败我留下我以前的 不正确 答案在这里:

你可以试试这个:

select AppID,  min(empid) EmpID, min(EmpName) EmpName 
from data
group by AppID

SQLFiddle: http://sqlfiddle.com/#!3/67cf0/1/0

MIN 忽略任何空值。

SQL Server 中 MIN 的文档:http://msdn.microsoft.com/en-us/library/ms179916.aspx

【讨论】:

这会给你带来不一致的结果。使用 AppId 2026880 的示例数据,您将得到 EmpId 和 Brad 的 9328 - EmpName 的 09628。

以上是关于在 SQL Server 中处理 Null 值和重复记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL-Server中NULL值的问题

SQL-Server to Access 处理 NULL

SQL Server 分析服务在维度字符串属性中传递空值和空白值

如何在 SQL Server 的触发器中获取多个字段的旧值和新值?

如何获取所有 SQL Server 默认值和规则的名称

sql中GROUPING的作用是啥