更有效的编写查询方式

时间:2017-07-25 21:12:24

标签: sql-server

我在#data表中有两个带有电子邮件地址的字段,我正在尝试加入。我希望它加入代表电子邮件地址,如果这不起作用,我希望它加入电子邮件。我尝试运行以下查询:

select a.*
from #data a
join #email b on b.email=coalesce(a.rep_email_address,a.email) 
where a.rep_email_address<>a.email

然而,这不起作用,因为在a.rep_email_adress不为空但与b.email不匹配的情况下,它将删除记录而不是取a.email字段。

这是我找到的解决办法:

select a.*
from #data a
join #email b on a.email=b.email
except 
select a.*
from #data a
join #email b on a.rep_email_address=b.email
union
select a.*
from #data a
join #email b on a.rep_email_address=b.email 
where a.rep_email_address<>a.email

然而,这远非最佳,所以我想知道 - 任何方式写这个以表现更好/看起来更清洁或更简单?只是为了澄清 - 这个查询有效(第二个查询),我想知道是否有更好的方法来编写它。

谢谢!

3 个答案:

答案 0 :(得分:3)

这应该简单得多。但是,我还建议您检查此查询的执行计划,以帮助您分析是否更优化。 [或者只是比较表格上的执行时间]

SELECT a.*
   FROM #data a
       JOIN #email b 
           ON (a.rep_email_address = b.email
               OR a.email = b.email )
WHERE a.rep_email_address<>a.email; 
# Not sure why or IF you need this where clause specifically.

答案 1 :(得分:1)

尝试这样......

SELECT
    a.*,
    SomeColumn = ISNULL(e1.SomeColumn, e2.SomeColumn)
from 
    #data a
LEFT JOIN #email e1
    ON e1.email = a.rep_email_address
LEFT JOIN #email e2 
    ON e2.email = a.email
    AND e1.email IS NULL 
WHERE 
    a.rep_email_address <> a.email
    AND (
            e1.email IS NOT NULL
            OR 
            e2.email IS NOT NULL
        );
HTH,Jason

答案 2 :(得分:1)

SQL服务器在布尔评估中使用“Three-Valued Logic”:

  • NULL <> 2 - &gt;未知(在你的情况下,在where子句中它将基本上变为假)
  • NULL <> NULL - &gt;未知(与上述相同)
  • a <> b - &gt;真

在您的情况下,您的原始查询应为:

select a.*
from #data a
join #email b on b.email=coalesce(a.rep_email_address,a.email) 
where ISNULL( a.rep_email_address, '' ) <> ISNULL( a.email, '' )

如果您关心性能,请尽量避免在连接谓词或WHERE条件中使用函数,因为这会阻止SQL Server在传递给函数的列上使用索引。

SELECT a.*
FROM #data AS a
    INNER JOIN #email AS b ON b.email = a.rep_email_address OR b.email = a.email
WHERE a.rep_email_address <> a.email OR ( a.rep_email_address IS NULL OR a.email IS NULL )

要点:

不要使用NULL来表示空字符串,因为这需要大量额外代码才能检查NULL s