在 T-SQL 中是否有一个内置命令来确定一个数字是否在另一个 table 的范围内

In T-SQL is there a built-in command to determine if a number is in a range from another table

这不是作业题。

我正在尝试计算订单中 T ​​恤的数量,并根据已订购的数量查看 T 恤属于哪个价格范围。 我最初的想法(我在这方面是全新的)是问另一个 table 是否计数 > 第一个价格范围的最大值,如果是,继续寻找直到不是。

printing_range_max  printing_price_by_range
15                  4
24                  3
33                  2

例如,如果订单数量为 30 件衬衫,则每件 2 美元。

当我研究如何做到这一点时,看起来大多数人都在使用 BETWEEN 或 IF 并对范围进行硬编码,而不是查看另一个 table。我想在商业环境中最好能够将范围保留在自己的 table 中,这样可以更轻松地更改它。有没有 good/built-in 方法可以做到这一点,还是我应该用 BETWEEN 命令或 IF 语句将其写入?

编辑: SQL 服务器 2014

假设我们有这个 table:

DECLARE @priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT @priceRanges VALUES (15, 4), (24, 3), (33, 2);

您可以创建一个 table,其中包含代表正确价格的范围。以下是在 2012 之前和 post-2012 系统中执行此操作的方法:

DECLARE @priceRanges TABLE(printing_range_max tinyint, printing_price_by_range tinyint);
INSERT @priceRanges VALUES (15, 4), (24, 3), (33, 2);

-- post-2012 using LAG
WITH pricerange AS
(
  SELECT 
    printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
    printing_range_max, 
    printing_price_by_range  
  FROM @priceRanges
)
SELECT * FROM pricerange;

-- pre-2012 using ROW_NUMBER and a self-join
WITH prices AS
(
  SELECT 
    rn = ROW_NUMBER() OVER (ORDER BY printing_range_max),
    printing_range_max, 
    printing_price_by_range  
  FROM @priceRanges
),
pricerange As
(
  SELECT 
    printing_range_min = ISNULL(p2.printing_range_max, 0),
    printing_range_max = p1.printing_range_max,
    p1.printing_price_by_range
  FROM prices p1
  LEFT JOIN prices p2 ON p1.rn = p2.rn+1
)
SELECT * FROM pricerange;

两个查询 return:

printing_range_min printing_range_max printing_price_by_range
------------------ ------------------ -----------------------
0                  15                 4
15                 24                 3
24                 33                 2

现在您可以使用 BETWEEN 加入。这是完整的解决方案:

-- Sample data
DECLARE @priceRanges TABLE
(
  printing_range_max tinyint, 
  printing_price_by_range tinyint
  -- if you're on 2014+
  ,INDEX ix_xxx NONCLUSTERED(printing_range_max, printing_price_by_range)
  -- note: second column should be an INCLUDE but not supported in table variables
);
DECLARE @orders TABLE 
(
  orderid int identity, 
  ordercount int
  -- if you're on 2014+ 
  ,INDEX ix_xxy NONCLUSTERED(orderid, ordercount)
  -- note: second column should be an INCLUDE but not supported in table variables
);

INSERT @priceRanges VALUES (15, 4), (24, 3), (33, 2);
INSERT @orders(ordercount) VALUES (10), (20), (25), (30);


-- Solution:
WITH pricerange AS
(
  SELECT 
    printing_range_min = LAG(printing_range_max, 1, 0) OVER (ORDER BY printing_range_max),
    printing_range_max, 
    printing_price_by_range  
  FROM @priceRanges
)
SELECT 
  o.orderid,
  o.ordercount,
  --p.printing_range_min, 
  --p.printing_range_max
  p.printing_price_by_range
FROM pricerange p
JOIN @orders o ON o.ordercount BETWEEN printing_range_min AND printing_range_max

结果:

orderid     ordercount  printing_price_by_range
----------- ----------- -----------------------
1           10          4
2           20          3
3           25          2
4           30          2

现在我们可以