SQL Query返回范围或最近范围内的项

时间:2009-09-04 09:54:47

标签: sql-server tsql

我有一个看起来像

的范围表
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.为了简单起见,我离开了该组。

在这个阶段,我真的不想改变数据库设计。

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

马克