仅当所有列都为空时才从其他表中选择

时间:2014-07-10 09:59:14

标签: sql sql-server sql-server-2008

我有以下SQL来获取员工的地址和其他信息。

SELECT   
  emp_id,  
  emp_name,
  @addr1 = ISNULL(ma.addr1, ba.addr1),  
  @addr2 = ISNULL(ma.addr2, ba.addr2),  
  @addr3 = ISNULL(ISNULL(ma.addr3, ba.addr3),''),  
  @addr4 = ISNULL(ISNULL(ma.addr4, ba.addr4),''),  
  @addr5 = ISNULL(ISNULL(ma.addr5, ba.addr5),''),  
  @postCode = ISNULL(ma.postcode, ba.postcode)  
 FROM dbo.employee e
 INNER JOIN MainAddress ma ON ma.AddressId=e.AddressId
 INNER JOIN SecondaryAddress ba ON ba.AddressId=e.AddressId

问题是当主地址中的Addr1或其他字段为NULL时,它会使用Addr3或其他辅助地址,并显示两个地址的混合。这完全无效。

当主地址中的所有字段都为NULL(不可用)时,如何获取辅助地址?

注意:用户可以更新两个表或只更新一个表。

1 个答案:

答案 0 :(得分:3)

如果“不可用”表示MainAddress表中没有记录,则ma.AddressId为空,因此,您可以对每个字段使用此条件:

  CASE WHEN ma.AddressId IS NULL THEN ba.addr1 ELSE ma.addr1 END,

如果你真的要检查所有字段是否为空,你必须改变这样的CASE条件:

  CASE WHEN 
    ma.addres1 IS NULL AND ma.addres2 IS NULL ...
  THEN ba.addr1 ELSE ma.addr1 END,

注意:如果有两种可能的情况,1,根本没有行,2,该行存在,但值都是null,你需要检查它:

ma.AddresId IS NULL OR (ma.addres1 IS NULL AND ma.addres2 IS NULL AND ...)

正如评论中所述,我忘了告诉您必须使用LEFT JOIN代替INNER JOIN。如果没有,如果任何地址表中没有员工记录,则查询不会返回该员工。

顺便说一句,如果您有一个地址表,并且带有一个指定地址类型的鉴别器列,那将会容易得多:主要或次要。如果您这样做,则只需从employee表中选择一个LEFT JOIN,并从地址表中选择一个TOP 1的查询。这将使您的应用程序开发人员在许多其他情况下更容易,例如查看您不知道它是否是主要的addresst。

更新:使用CTE

至于OP评论,有必要使用长表达式。为了使其更清晰和可维护,可以像这样使用CTE:

WITH ea AS -- the CTE, ea includes "employee + MainAdressExists column"
(
SELECT 
    *, -- select the required columns
    -- plus an extra calculated column
    CASE WHEN 
       ma.address1 IS NOT NULL 
       OR ma.address2 IS NOT NULL
       -- add here all the column checks
    THEN 1 ELSE 0 END AS MainAddressExists 
FROM employee e
LEFT JOIN MainAddres ma ON ma.IdAddress = e.IdAdress
)
SELECT
  -- choose the needed fields from ea
  CASE WHEN P.MainAddressExists = 1 THEN ma.addres1 ELSE ba.address1 END 
  AS address1,
  -- choose all the other address fields
FROM ea
LEFT JOIN MainAddress ma ON ma.AddressId=e.AddressId
LEFT JOIN SecondaryAddress ba ON ba.AddressId=e.AddressId