我有一个看起来像
的范围表CREATE TABLE [dbo].[WeightRange](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Description] [nvarchar](50) NULL,
[LowerBound] [decimal](18, 2) NULL,
[UpperBound] [decimal](18, 2) NULL,
[GroupID] [int] NULL
)
鉴于权重和组ID,我需要找到匹配(或最近的)范围ID。
实施例
WeightRanges
1, 0-100kgs, 0, 100, 1
2, 101-250kgs, 101, 250, 1
3, 501-1000kgs, 501, 1000, 1
如果权重是10,它应该返回id 1,如果权重是1500,它应该返回id 3,如果权重是255,它应该返回id 2.为了简单起见,我离开了该组。
在这个阶段,我真的不想改变数据库设计。
答案 0 :(得分:3)
我使用CASE语句创建一个带有“距离”的列,然后按距离排序并获取第一个项目。
可能有用的代码段:
SELECT TOP 1 d.id
FROM (
SELECT id, CASE WHEN (@weight >= LowerBound)
AND (@weight <= UpperBound) THEN 0
WHEN (@weight < LowerBound) THEN LowerBound-@weight
WHEN (@weight > UpperBound) THEN @weight-UpperBound
END AS distance
FROM WeightRange
) d
WHERE d.distance IS NOT NULL
ORDER BY d.distance ASC
答案 1 :(得分:1)
我认为这个存储函数应该是技巧 - 它在内部使用CTE(公用表表达式),因此它将适用于SQL Server 2005及更高版本:
CREATE FUNCTION dbo.FindClosestID(@WeightValue DECIMAL(17,2))
RETURNS INT
AS BEGIN
DECLARE @ReturnID INT;
WITH WeightDistance AS
(
SELECT ID, ABS(Lowerbound - @WeightValue) 'Distance'
FROM WeightRange
UNION ALL
SELECT ID, ABS(upperbound - @WeightValue) 'Distance'
FROM WeightRange
)
SELECT TOP 1 @ReturnID = ID
FROM WeightDistance
ORDER BY Distance
RETURN @ReturnID
END
这些查询将返回以下值:
SELECT
dbo.FindClosestID(75.0),
dbo.FindClosestID(300.0),
dbo.FindClosestID(380.0),
dbo.FindClosestID(525.0),
dbo.FindClosestID(1500.0)
1 2 3 3 3
马克