2009-09-04 66 views
1

返回一個項目我有範圍的表看起來像SQL查詢範圍之內或附近範圍

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.我已經離開爲了簡單起見,該小組不在此列。

在這個階段我並不想改變數據庫設計。

回答

3

我會使用一個CASE語句來創建與「距離」,然後按距離列,並採取的第一個項目。

片段可以幫助:

SELECT TOP 1 d.id 
    FROM (
     SELECT id, CASE WHEN (@weight >= LowerBound) 
          AND (@weight <= UpperBound) THEN 0 
         WHEN (@weight < LowerBound) THEN [email protected] 
         WHEN (@weight > UpperBound) THEN @weight-UpperBound 
        END AS distance 
      FROM WeightRange 
     ) d 
    WHERE d.distance IS NOT NULL 
    ORDER BY d.distance ASC 
+0

做了伎倆,謝謝。 – 2009-09-04 12:41:38

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 

馬克

+0

你的算法可能會返回錯誤的結果,如果範圍接觸或重疊。假定範圍1:0-10,範圍2:9-20,即使值在範圍1中,值8也會返回範圍2. – Lucero 2009-09-04 12:27:01

+0

範圍應該*不*重疊! :-)真的沒有道理,在我看來...... – 2009-09-04 13:05:51