2009-09-04 11 views
1

内の項目を返すために、私は、一致(または最寄りの)範囲のIDを見つける必要がある重量とグループIDが与え 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 
) 

のように見える範囲のテーブルを持っています。例

WeightRanges 
1, 0-100kgs,  0, 100, 1 
2, 101-250kgs, 101, 250, 1 
3, 501-1000kgs, 501, 1000, 1 

重量は、それは、ID 1を返す必要があり、重量が1500である場合、それは、ID 3返す必要があり、重量が255である場合、それは私が残ったID 2を返す必要が10である場合

単純化のために例の外にあるグループ。

この段階では、実際にデータベース設計を変更する必要はありません。

私は、この保存された関数はトリックにすべきだと思う

答えて

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

そのトリックをした、ありがとう。 –

1

- それはSQL Server 2005およびアップで動作しますので、それは、内部CTE(共通テーブル式)を使用しています。

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

+0

範囲は重複しないはずです*! :-)私の意見では、実際に意味をなさない... –