我有以下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(不可用)时,如何获取辅助地址?
注意:用户可以更新两个表或只更新一个表。
答案 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