我有三个表 - 一个用于运费,一个用于产品,一个用于特定产品的运费率例外。运费如下: 每种产品都有运费,但这个价格可以被例外覆盖。如果产品不存在例外,则默认费率用于用户选择的运费。 alt text http://mi6.nu/sqljoin.png 我正在尝试加入这些表,以便如果存在例外,则选择该价格,否则,选择默认价格但我遇到了加入问题。我需要按产品ID查询,我有(第2行用于调试)
SELECT r.ID AS ShippingRateID, r.Name,
e.*, r.*
FROM shipping r LEFT JOIN shippingexceptions e ON r.ID = e.ShippingRateID
WHERE e.ProductID = 48
我需要回复:
1 Uk and Northern Ireland 1
2 EU Eire... 10
3 US and Canada 2.16
4 Rest of world 2.44
因此,如果存在例外,则使用例外价格,否则使用默认价格。我打算使用CASE语句,但我需要先返回数据。
答案 0 :(得分:8)
为什么不使用合并
SELECT r.ID AS ShippingRateID, r.Name, coalesce(e.cost, r.defaultprice)
FROM shipping r LEFT JOIN shippingexceptions e ON r.ID = e.ShippingRateID
WHERE e.ProductID = 48
这样,如果e.rate为null,则使用r.rate。
您还应该将e.ProductId放在连接上,这样就不会强迫您只选择有异常的产品
SELECT r.ID AS ShippingRateID, r.Name, coalesce(e.cost, r.defaultprice)
FROM shipping r LEFT JOIN shippingexceptions e ON r.ID = e.ShippingRateID and e.ProductID = 48
答案 1 :(得分:4)
我注意到的第一件事是你在表e上有一个谓词条件,它位于外连接的“外”侧。这将立即将连接转换为内部连接,因为在内侧有记录但外侧没有记录的情况下,通常会产生的行将在外部表的列中具有所有空值。时间执行where子句谓词(WHERE e.ProductID = 48)。
您需要将此谓词放在连接条件中 像这样:
SELECT r.ID AS ShippingRateID, r.Name, e.*, r.*
FROM shipping r
LEFT JOIN shippingexceptions e
ON r.ID = e.ShippingRateID
And e.ProductID = 48
接下来,正如Joels回答推荐的那样,对于一个简单的表达式,虽然案例可行,但您不需要案例陈述,Coalesce就足够了:
SELECT r.ID AS ShippingRateID, r.Name,
Coalesce(e.rate, defaultrate) as Rate,
e.*, r.*
FROM shipping r
LEFT JOIN shippingexceptions e
ON r.ID = e.ShippingRateID
And e.ProductID = 48
答案 2 :(得分:1)
如果您使用MSSQL,COALESCE功能会有所帮助。它首先返回not-null。
是的,
select COALESCE(shippingexceptions.Rate, shipping.Rate )
对案例做同样的事情......时:
Select Case when shippingexceptions.Rate is not null THEN shippingexceptions.Rate
ELSE shipping.Rate
希望这会有所帮助..
答案 3 :(得分:0)
SELECT COALESCE(
(
SELECT TOP 1 cost
FROM shippingexceptions se
WHERE se.ShippingRateID = r.id
AND se.ProductID = 48
), DefaultPrice
) AS price
FROM shipping r
,或SQL Server 2005+
:
SELECT COALESCE(cost, DefaultPrice) AS price
FROM shipping r
OUTER APPLY
(
SELECT TOP 1 cost
FROM shippingexceptions
WHERE ShippingRateID = r.id
AND ProductID = 48
) se