ISNULL / COALESCE用于多个领域

时间:2013-04-15 04:07:10

标签: sql-server tsql join coalesce

考虑以下数据模型:

客户

CustNum | First Name | Last Name
  555        John         Doe

CustomerAddresses

CustNum | ShippingAddress|     Line1      |  Line2  |   City  | State |  Zip    
  555   |     ADD1       |   333 A Dr.    | Apt. 10 | Dallas  |  TX   | 11345  
  555   |     ADD2       |   111 B St.    |  NULL   | Miami   |  FL   | 22222
  555   |     WXYZ       |  123 Main St.  |  NULL   | Detroit |  MI   | 99998

OrderHeader

OrdNum | CustNum | OrderTotal |     Line1     | Line2 |   City  | State|  Zip
 1000  |   555   |   67.00    | 123 Main St.  | Ste 1 | Detroit |  MI  | 99998

订单行

OrderNo  | Item  |  Price  | ShippingAddress  
 1000    | X123  |  32.00  |     ADD1
 1000    | Y234  |  25.00  |     ADD2
 1000    | ZZZZ  |  10.00  |     NULL  

客户与CustomerAddresses之间存在一对多的关系 每个OrderHeader,而不是与CustomerAddresses表的关键关系,在Line1,Line2,City,State和Zip字段中存储用于装运的地址。
此外,还可以在OrderLine表中选择一个覆盖OrderHeader中存储的地址的送货地址。
我正在尝试用以下格式返回数据的查询,以生成邮件标签列表:
MailingLabels

OrderNo  | Item  |     Line1      |  Line2  |   City  | State |  Zip     
 1000    | X123  |   333 A Dr.    | Apt. 10 | Dallas  |  TX   | 11345
 1000    | Y234  |   111 B St.    |  NULL   | Miami   |  FL   | 22222
 1000    | ZZZZ  |  123 Main St.  |  NULL   | Detroit |  MI   | 99998   

基本上,如果OrderLine记录具有ShippingAddress值,我想从CustomerAddresses表中返回相应的地址。
如果它为NULL,那么我想返回存储在OrderHeader表中的Line1,Line2,City,State和Zip值。
问题是,当我使用COALESCE或ISNULL时,可能会返回不正确的结果。这是我的疑问:

SELECT OH.OrderNo, Item, ISNULL(CA.Line1, OH.Line1), ISNULL(CA.Line2, OH.Line2),  
       ISNULL(CA.City, OH.City), ISNULL(CA.State, OH.State), ISNULL(CA.Zip, OH.Zip)
FROM   OrderHeader OH
JOIN   OrderLine OL
ON     OH.OrderNo = OL.OrderNo
LEFT JOIN   CustomerAddress CA
ON     OL.CustNum = CA.CustNum
AND    OL.ShippingAddress = CA.ShippingAddress  

使用上述查询,如果为OrderHeader定义了Line2字段,但在OrderLine中定义了ShippingAddress,则可以返回Y234项目的混合地址:

OrderNo | Item |   Line1   |  Line2  |   City  | State |  Zip            
1000    | Y234 | 111 B St. |  Ste 1  |  Miami  |  FL   | 22222  

注意,Ste 1不是OrderLine中表示的地址的一部分,它实际上是OrderHeader的一部分。
如何编写查询以按所需方式返回数据?非常感谢任何和所有的帮助!

1 个答案:

答案 0 :(得分:6)

不幸的是,我不能想到一个简洁的方法来做到这一点,而不是非常重复。

假设OL别名应该是CA

SELECT OH.OrderNo, Item,
       CASE WHEN OL.ShippingAddress IS NULL THEN OH.Line1 ELSE CA.Line1 END,
       CASE WHEN OL.ShippingAddress IS NULL THEN OH.Line2 ELSE CA.Line2 END,
       CASE WHEN OL.ShippingAddress IS NULL THEN OH.City ELSE CA.City END,
       CASE WHEN OL.ShippingAddress IS NULL THEN OH.State ELSE CA.State END,
       CASE WHEN OL.ShippingAddress IS NULL THEN OH.Zip ELSE CA.Zip END
FROM   OrderHeader OH
JOIN   OrderLine OL
ON     OH.OrderNo = OL.OrderNo
LEFT JOIN   CustomerAddress CA
ON     OL.CustNum = CA.CustNum
AND    OL.ShippingAddress = CA.ShippingAddress