And*_*rew 1 sql t-sql sql-server
我有一个SQL查询,该查询根据租金的持续时间返回价格水平。该表包含以下列:
ProductID (UNIQUEIDENTIFIER), MinDuration(INT), MaxDuration(INT), Price (DECIMAL(10, 4)
Run Code Online (Sandbox Code Playgroud)
我当前使用的查询的简化版本是:
SELECT Price
FROM RentalPrices
WHERE ProductID = @ProductID
AND @Duration BETWEEN MinDuration AND MaxDuration;
Run Code Online (Sandbox Code Playgroud)
表例
+--------------------------------------+-------------+-------------+-------+
| 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 |
+--------------------------------------+-------------+-------------+-------+
Run Code Online (Sandbox Code Playgroud)
我的问题是,大于或等于31的值将找不到最后一行,即开放式最大值,有没有一种好的简单方法来处理此问题?我知道一些可能会起作用的选项,但是不确定什么是最好的。
BETWEEN MinDuration AND ISNULL(MaxDuration,2147483647)
@Duration >= MinDuration AND (@Duration <= MaxDuration OR MaxDuration IS NULL)
特别是目标是在最大数量的情况下提高效率,我们很少会碰到最后一个值(在实际表中不是一个月,而是六个月以上,取决于所用的产品)因此,最有效的解决方案是持续时间在两个值之间,同时仍能处理上限为空且效率良好的情况。
最有效的方法可能是忽略maxduration
!
SELECT TOP (1) Price
FROM ?
WHERE ProductID = @ProductID AND MinDuration <= @Duration
ORDER BY MinDuration DESC;
Run Code Online (Sandbox Code Playgroud)
这可以利用上的索引(ProductId, MinDuration)
。
至于你的问题本身。我投票赞成将最大值存储在表中,而不是NULL
用于此目的。这不是最美观的解决方案,但可以简化编码。您建议的两种方法之间的选择实际上是关于美学的(尽管我将使用ANSI标准COALESCE()
)。