【问题标题】:How to INNER JOIN on non-empty values BUT AT THE SAME TIME LEFT JOIN on empty values?如何在非空值上进行 INNER JOIN 但在同一时间 LEFT JOIN 上的空值?
【发布时间】:2014-06-19 15:45:41
【问题描述】:

看来我需要一个MAGIC JOIN,它应该在非空值上作为INNER JOIN 工作,但同时在空值上作为LEFT JOIN 工作。 “空”是指非空零长度 char 值,如下所示:''

我有桌子Customers

CustomerCode    Customer_AddressCode
CC01            AC01
CC02            somebullcrap
CC03
CC04            AC02
CC05

Addresses:

AddressCode    AddressValue
AC01           City 01
AC02           City 02
AC03           City 03
AC04           City 04
AC05           City 05

想要的输出是这样的:

CustomerCode  AddressValue
CC01          City 01
CC03          NULL
CC04          City 04
CC05          NULL

所以它会省略在Addresses 表中不存在的带有代码somebullcrap 的地址。

我能想到的最好的是:

SELECT c.CustomerCode, a.AddressValue
FROM Customers c
LEFT JOIN Addresses a ON a.AddressCode = c.Customer_AddressCode
WHERE c.Customer_AddressCode = ''
OR c.Customer_AddressCode IN
(
    SELECT AddressCode
    FROM Address
)

有没有更优雅的解决方案?

是的,我确实知道可为空的外键。我只是在询问解决方案,无需更改表/制作临时表/修改现有表数据。

【问题讨论】:

    标签: sql-server tsql left-join inner-join


    【解决方案1】:

    为什么不

    SELECT c.CustomerCode, a.AddressValue
    FROM Customers c
    LEFT JOIN Addresses a 
       ON a.AddressCode = c.Customer_AddressCode
    WHERE c.Customer_AddressCode = ''
       OR a.AddressValue IS NOT NULL
    

    【讨论】:

    • 执行计划方面,这是“最优雅的”。
    【解决方案2】:

    你想要的只是一个左连接,因为在你的地址表中没有带有空字符串的地址作为代码。我认为这会给你想要的结果:

    SELECT c.CustomerCode, a.AddressValue
    FROM Customers c
    LEFT JOIN Addresses a ON a.AddressCode = c.Customer_AddressCode
    

    为什么客户和地址之间的外键没有CHECK?

    【讨论】:

    • 请注意,我现在在问题中看到您想完全省略以 somebullcrap 作为地址 ID 的客户记录。抱歉,这行不通。
    【解决方案3】:

    如果您的问题是处理空字符串 ( '' ),您可以使用简单的

    CASE Customer_AddressCode='' THEN NULL ELSE Customer_AddressCode END
    

    将您的空字符串转换为真正的NULL 值。
    然后,一个简单的LEFT JOIN 像这样:

    SELECT c.CustomerCode, a.AddressValue
    FROM 
    (SELECT 
        CustomerCode, 
        CASE Customer_AddressCode='' THEN NULL ELSE Customer_AddressCode END AdCode
    FROM Customers) c
    LEFT JOIN Addresses a ON (a.AddressCode = c.AdCode OR c.AdCode is null)
    

    c.AdCode is null 条件将允许结果中有空值,同时过滤您似乎不想要的“somebullcrap”。

    【讨论】:

      【解决方案4】:

      EricZ 可能是最优雅的方法,可以返回正确的结果,但只是作为替代方法的练习:

      SELECT  c.CustomerCode
            , a.AddressValue FROM    Customers c
              JOIN ( SELECT   AddressCode
                            , AddressValue
                     FROM     Addresses
                     UNION ALL
                     SELECT   ''
                            , NULL
                   ) a ON a.AddressCode = c.Customer_AddressCode
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-11
        • 2016-12-14
        • 2012-09-10
        • 1970-01-01
        • 2021-11-21
        • 2021-06-20
        • 2017-04-06
        • 1970-01-01
        相关资源
        最近更新 更多