有效的WHERE子句检查minumim和NULL之间的值

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)

特别是目标是在最大数量的情况下提高效率,我们很少会碰到最后一个值(在实际表中不是一个月,而是六个月以上,取决于所用的产品)因此,最有效的解决方案是持续时间在两个值之间,同时仍能处理上限为空且效率良好的情况。

Gor*_*off 5

最有效的方法可能是忽略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())。