在SQL Server 2014的数据库中,我有一个CustomerRecords
表,其中包含地址列Address
,City
,State
,Zip
。
我还有一个CustomerBillingAddresses
表,与CustomerRecords
上CustomerID
的FK关系。此表还包含Address, City, State, Zip
列,但另外还有Active
(位)列。每个CustomerID
只能有一个活动记录。
并非所有CustomerRecords
都位于CustomerBillingAddresses
,并且CustomerBillingAddresses
中的所有记录都不是有效的Active=1
)
我想要返回这样的客户信息:
CustomerID, Name, Address, City, State, Zip
但是如果CBA中的CustomerRecords
位为真,我只想从CustomerBillingAddresses
或Active
返回一组地址信息。
到目前为止,我有这个:
SELECT DISTINCT
cr.CustomerID, cr.CustomerName,
CASE
WHEN cba.CustomerID IS NOT NULL
THEN cba.Address
ELSE cr.Address
END AS Address,
CASE
WHEN cba.CustomerID IS NOT NULL
THEN cba.City
ELSE cr.City
END AS City,
CASE
WHEN cba.CustomerID IS NOT NULL
THEN cba.State
ELSE cr.State
END AS State,
CASE
WHEN cba.CustomerID IS NOT NULL
THEN cba.Zip
ELSE cr.Zip
END AS Zip
FROM
dbo.CustomerRecords cr
LEFT JOIN
dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
AND cba.Active = 1
当找到活动的CBA地址时,我无法排除CR地址,因为它们附加到基本记录CustomerID。我意识到这是糟糕的数据库形式,但它是我必须使用的。此外,规范化不会像这样有趣,对吗?
问题
我的查询实际上得到了我想要的结果,并且似乎没有比原始查询更糟糕的表现,但我确信有更好的方法。
我一遍又一遍地重复看到“cba.CustomerID IS NOT NULL”的情况......
我提前感谢任何帮助,建议或解答。
答案 0 :(得分:0)
您的查询给人的印象是,如果某行的cba.CustomerID为NULL,则该行的每个其他字段都将为空,应该被忽略。
在这种情况下,您可以使用COALESCE表达式。
COALESCE expression returns the first non-null expression in the list to be evaluated.
SELECT DISTINCT cr.CustomerID, cr.CustomerName, COALESCE(cba.Address,
cr.Address) AS Address,
COALESCE(cba.City, cr.City) AS City, COALESCE(cba.State, cr.State) AS State,
COALESCE(cba.Zip, cr.Zip) AS Zip
FROM dbo.CustomerRecords cr
LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
AND cba.Active = 1
或者你可以简单地使用ISNULL函数。
SELECT DISTINCT cr.CustomerID, cr.CustomerName, ISNULL(cba.Address,
cr.Address) AS Address,
ISNULL(cba.City, cr.City) AS City, ISNULL(cba.State, cr.State) AS State,
ISNULL(cba.Zip, cr.Zip) AS Zip
FROM dbo.CustomerRecords cr
LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
AND cba.Active = 1
答案 1 :(得分:0)
如果dbo.CustomerBillingAddresses不可为空,则当cba.CustomId为null时,cba.Address为NULL。所以你可以直接检查cba.Address。
SELECT DISTINCT cr.CustomerID, cr.CustomerName,
COALESCE(cba.Address, cr.Address) AS Address
...other columns
FROM dbo.CustomerRecords cr
LEFT JOIN dbo.CustomerBillingAddresses cba ON cba.CustomerID = cr.CustomerID
AND cba.Active = 1
答案 2 :(得分:0)
我有办法解决这个问题,但它可能仍然会让你感到畏缩,我也不知道这个表现。
方式只是union
- 2个查询,第一个用于Active = 0,第二个用于Active = 1.您只需要从相应的列获取。无需case when
或coalesce
例如:
select t1.address, t1.city from table1 t1 where t1.active = 0
union
select t2.address, t2.city from table1 t1
inner join table2 t2 on t1.customer = t2.customer where t1.active = 1