我有一个SQL查询,它根据租借期限返回价格水平。该表有列:
ProductID (UNIQUEIDENTIFIER), MinDuration(INT), MaxDuration(INT), Price (DECIMAL(10, 4)
我目前使用的查询的简化版本是:
SELECT Price
FROM RentalPrices
WHERE ProductID = @ProductID
AND @Duration BETWEEN MinDuration AND MaxDuration;
表格示例
+--------------------------------------+-------------+-------------+-------+
| ProductID | MinDuration | MaxDuration | Price |
+--------------------------------------+-------------+-------------+-------+
| e93d19e1-142f-41cc-8f39-9cf7607717ac | 0 | 3 | 25 |
| e93d19e1-142f-41cc-8f39-9cf7607717ac | 4 | 7 | 50 |
| e93d19e1-142f-41cc-8f39-9cf7607717ac | 8 | 14 | 100 |
| e93d19e1-142f-41cc-8f39-9cf7607717ac | 15 | 30 | 200 |
| e93d19e1-142f-41cc-8f39-9cf7607717ac | 31 | NULL | 500 |
+--------------------------------------+-------------+-------------+-------+
我的问题是大于或等于31的值不会找到最后一行,即开放式最大值,是否有一个好的,简单的方法来处理它?我知道一些可能有用的选项,但我不确定什么是最好的。
BETWEEN MinDuration AND ISNULL(MaxDuration,2147483647)
@Duration >= MinDuration AND (@Duration <= MaxDuration OR MaxDuration IS NULL)
特别是目标是效率超过最大数量的情况,我们最终达到最后一个价值的情况很少见(在实际表格中它不是一个月,但可能是六个月以上的任何一个月) ,取决于正在租用的产品),因此最有效的解决方案是在两个值之间的持续时间,同时仍然处理上限为空,效率良好的情况,是目标。
答案 0 :(得分:4)
最有效的方法可能是忽略maxduration
!
SELECT TOP (1) Price
FROM ?
WHERE ProductID = @ProductID AND MinDuration <= @Duration
ORDER BY MinDuration DESC;
这可以使用(ProductId, MinDuration)
上的索引。
至于你的问题本身。我会投票支持在表格中存储最大值,而不是为此目的使用NULL
。不是最美观的解决方案,但它简化了编码。你提出的两种方法之间的选择实际上是关于美学(虽然我会使用ANSI标准COALESCE()
)。
答案 1 :(得分:3)
效率不高但我觉得很干净
SELECT Price
FROM RentalPrices
WHERE ProductID = @ProductID
AND @Duration BETWEEN MinDuration AND isnull(MaxDuration, @Duration);
考虑ProductID上的群集PK,价格
declare @rental table (id int not null, minDuration int not null, maxDuration int, price int not null);
insert into @rental (id, minDuration, maxDuration, price) values
(1, 0, 3, 25)
, (1, 4, 7, 50)
, (1, 8, 14, 100)
, (1, 15, 30, 200)
, (1, 31, null, 500);
declare @id int = 1;
declare @duration int = 15;
select id, minDuration, maxDuration, price
from @rental
order by id, MinDuration;
SELECT Price, @duration, minDuration, maxDuration
FROM @rental
WHERE id = @id
AND @duration BETWEEN minDuration AND isnull(maxDuration, @Duration)
order by id, minDuration;