用于检查 NULLS 和不存在记录的 SQL Case 语句

Posted

技术标签:

【中文标题】用于检查 NULLS 和不存在记录的 SQL Case 语句【英文标题】:SQL Case statement to check for NULLS and Non-existent records 【发布时间】:2010-11-24 22:07:45 【问题描述】:

我正在两个表之间进行连接,并希望根据它们是否有记录来选择列。我试图避免有多个相同的字段,并试图将它们压缩成单列。比如:

Select 
    id = (CASE WHEN a.id IS NULL THEN b.id ELSE a.id END),
    name = (CASE WHEN a.name IS NULL THEN b.name ELSE a.name END)
From Table1 a
Left Join Table2 b
On a.id = b.id
Where a.id = @id

如果记录存在,我希望 idTable1 填充,但如果不从 Table2 提取。前面的代码没有返回任何记录,因为Table1 中没有NULL 值所以我的问题是如何运行检查以查看是否存在任何记录?此外,如果有人知道更好的方法来完成我正在尝试做的事情,我感谢指导和建设性的批评。

编辑

看起来COALESCE 将适用于我想要完成的工作。我想提供更多关于我正在使用什么的信息,并就我是否使用最好的方法获得一些建议。

我有一张臃肿的桌子Table2,它正在生产中。我正在为此系统构建新的 Web 应用程序,但无法证明重新设计完整的数据库是合理的,因此我正在尝试“即时”做一个。我创建了一个新表Table1,我正在为以下方法编写存储过程Get(Select)、Set(Update)、Add(Insert)、Remove (Delete)。这样,对于我的代码,我似乎正在使用一个不臃肿的表。我的代码将简单地调用其中一种 SP 方法,然后存储过程将处理旧表和新表之间的数据。我目前正在研究Get 方法,如果Table1 中不存在旧表Table2,我需要检查它以获取记录。 感谢这里的建议,我的查询目前看起来像这样:

Select
    id = coalesce(a.id, b.student_number),
    first_name = coalesce(a.first_name, b.first_name),
    last_name = coalesce(a.last_name, b.last_name),
    //etc
From Table1 a
Full Outer Join Table2 b
On a.id = b.student_number
Where (a.id = @id Or b.student_number = @id)

这适用于我想要完成的工作,如果有更好或更正确的方法来解决这个问题,我想把它扔给有经验的人群以获得任何提示或建议。

谢谢

【问题讨论】:

【参考方案1】:

我怀疑您的问题可能来自左连接。再次尝试使用完全外连接,如下所示:

Select 
    id = coalesce(a.id, b.id),
    name = coalesce(a.name, b.name)
From Table1 a
full outer Join Table2 b
On a.id = b.id
Where a.id = @id

【讨论】:

【参考方案2】:
Select id = coalesce(a.id, b.id), 
    name = coalesce(a.name, b.name)
From Table2 b 
Left Join Table1 a On a.id = b.id 
Where b.id = @id 

您可能需要使用ISNULLCASE 而不是COALESCE,具体取决于您的数据库平台。

【讨论】:

【参考方案3】:

首先,您不需要 case 语句:

Select ISNULL(a.id,b.id) AS id, ISNULL(a.name,b.name) AS name,
From Table1 a
Left Join Table2 b
On a.id = b.id
Where a.id = @id

其次,如果我做对了,id 字段可以包含空值,在这种情况下你就完蛋了。我的意思是,ID 是标识行的唯一值,如果它可以为 null,则无法标识该行。

但是,如果您想要从 Table1 和 Table2 中获取记录并避免重复,那么简单的 UNION 就可以正常工作,因为它会丢弃重复项:

select id, name
from Table1
where id = @id

union

select id, name
from Table2
where id = @id

【讨论】:

正确,ID 字段永远不会为 NULL,我只是将 id 和 name 作为示例列,而不是放置我正在处理的所有真实列。我已经用更多关于我一直在努力完成的事情的信息更新了这个问题。感谢您的帮助。【参考方案4】:

你可以这样做:

select id, name from Table1 a where a.id not in (select id from Table2) 联盟 从 Table2 中选择 id、名称 b

这将为您提供 table1 中在 table2 中没有对应匹配项的所有记录以及 table2 的所有记录。然后联合将合并结果。

【讨论】:

【参考方案5】:

在您的第一个 CASE 语句中,a.id 和 b.id 将始终具有相同的值,除了 a.id 具有值且 b.id 由于 LEFT JOIN 生成 NULL 值的实例。结果集中永远不会有一行具有 NULL a.id 值和非 NULL b.id 值。您可以在此列中使用 a.id。

对于第二个 CASE 语句,您可能会在一个或两个表中找到带有值的 name 列(当然,值可能不同)。您说要“压缩”这些列值;其 SQL 函数是 COALESCE:

 COALESCE(a.id, b.id)

返回第一个非 NULL 值(如果不是 NULL,则为 a.id,否则为 b.id)。它不会提示您在两个表中使用不同的名称。

【讨论】:

以上是关于用于检查 NULLS 和不存在记录的 SQL Case 语句的主要内容,如果未能解决你的问题,请参考以下文章

Mysql- SELECT列'A',即使使用NULLS

插入和不存在的插入之间的性能差异

当我不想要的时候,Linq to SQL Join 允许 Nulls

SQL 检查记录是不是存在

SQL - 如果存在不适用于 Select 语句?

如何使用 SQL 检查记录是不是存在?