Gre*_*reg 5 sql sql-server database-design sql-server-2008
我正在尝试编写一个查询,告诉我哪些订单有有效的promocodes.促销代码仅仅是某些日期之间有效的可选某些包.
我甚至无法解释它是如何工作的(参见下面的psudo-ish代码),但基本上如果有与promocode相关联的包,那么订单必须有一个这样的包并且在有效的日期范围内,否则它只需要处于有效的日期范围内.
整个"如果PrmoPackage行存在"的事情真的让我失望了,我觉得我应该能够在没有一大堆Union
s的情况下做到这一点.(我甚至不确定在这一点上是否会让它更容易......)
有人对查询有任何想法吗?
if `OrderPromoCode` = `PromoCode`
then if `OrderTimestamp` is between `PromoStartTimestamp` and `PromoEndTimestamp`
then if `PromoCode` has packages associated with it
//yes
then if `PackageID` is one of the specified packages
//yes
code is valid
//no
invalid
//no
code is valid
Run Code Online (Sandbox Code Playgroud)
订购:
OrderID* | OrderTimestamp | PackageID | OrderPromoCode
1 | 1/2/11 | 1 | ABC
2 | 1/3/11 | 2 | ABC
3 | 3/2/11 | 2 | DEF
4 | 4/2/11 | 3 | GHI
Run Code Online (Sandbox Code Playgroud)
促销:
PromoCode* | PromoStartTimestamp* | PromoEndTimestamp*
ABC | 1/1/11 | 2/1/11
ABC | 3/1/11 | 4/1/11
DEF | 1/1/11 | 1/11/13
GHI | 1/1/11 | 1/11/13
Run Code Online (Sandbox Code Playgroud)
PromoPackage:
PromoCode* | PromoStartTimestamp* | PromoEndTimestamp* | PackageID*
ABC | 1/1/11 | 2/1/11 | 1
ABC | 1/1/11 | 2/1/11 | 3
GHI | 1/1/11 | 1/11/13 | 1
Run Code Online (Sandbox Code Playgroud)
期望的结果:
OrderID | IsPromoCodeValid
1 | 1
2 | 0
3 | 1
4 | 0
Run Code Online (Sandbox Code Playgroud)
;WITH PromoCTE AS
( SELECT promo.*, CASE WHEN p.PromoCode IS NULL THEN 0 ELSE 1 END [HasPackage]
FROM Promo
LEFT JOIN
( SELECT DISTINCT PromoCode
FROM PromoPackage
) p
ON promo.PromoCode = p.PromoCode
)
SELECT [Order].OrderID,
CASE WHEN COUNT(CASE WHEN HasPackage = 1 THEN PromoPackage.PromoCode ELSE Promo.PromoCode END) >= 1 THEN 1 ELSE 0 END [IsPromoCodeValid]
FROM [Order]
LEFT JOIN PromoCTE promo
ON Promo.PromoCode = [Order].OrderPromoCode
AND [Order].OrderTimeStamp BETWEEN Promo.PromoStartTimestamp AND Promo.PromoEndTimestamp
LEFT JOIN PromoPackage
ON PromoPackage.PromoCode = OrderPromoCode
AND PromoPackage.PackageID = [Order].PackageID
AND [Order].OrderTimeStamp BETWEEN PromoPackage.PromoStartTimestamp AND PromoPackage.PromoEndTimestamp
GROUP BY [Order].OrderID;
Run Code Online (Sandbox Code Playgroud)
非 CTE 版本
SELECT [Order].OrderID,
CASE WHEN COUNT(CASE WHEN HasPackage = 1 THEN PromoPackage.PromoCode ELSE Promo.PromoCode END) >= 1 THEN 1 ELSE 0 END [IsPromoCodeValid]
FROM [Order]
LEFT JOIN
( SELECT promo.*, CASE WHEN p.PromoCode IS NULL THEN 0 ELSE 1 END [HasPackage]
FROM Promo
LEFT JOIN
( SELECT DISTINCT PromoCode
FROM PromoPackage
) p
ON promo.PromoCode = p.PromoCode
) promo
ON Promo.PromoCode = [Order].OrderPromoCode
AND [Order].OrderTimeStamp BETWEEN Promo.PromoStartTimestamp AND Promo.PromoEndTimestamp
LEFT JOIN PromoPackage
ON PromoPackage.PromoCode = OrderPromoCode
AND PromoPackage.PackageID = [Order].PackageID
AND [Order].OrderTimeStamp BETWEEN PromoPackage.PromoStartTimestamp AND PromoPackage.PromoEndTimestamp
GROUP BY [Order].OrderID;
Run Code Online (Sandbox Code Playgroud)