在 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
现在我们可以
这不是作业题。
我正在尝试计算订单中 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
现在我们可以