如何从另一个表中动态查找范围的数字范围?

时间:2010-08-23 23:56:54

标签: sql sql-server database tsql

如果我有两张桌子:

PersonID | Count
-----------------
1        | 45
2        | 5
3        | 120
4        | 87
5        | 60
6        | 200
7        | 31

SizeName | LowerLimit
-----------------
Small    | 0
Medium   | 50
Large    | 100

我正在试图弄清楚如何进行查询以获得类似的结果:

PersonID | SizeName
-----------------
1        | Small
2        | Small
3        | Large
4        | Medium
5        | Medium
6        | Large
7        | Small

基本上,一个表指定了未知数量的“范围名称”及其相关的整数范围。因此,人员表中的0到49的计数范围得到“小”指定。 50-99获得'中等'等等。但我需要它是动态的,因为我不知道范围名称或整数值。我可以在单个查询中执行此操作,还是必须编写单独的函数来循环使用这些可能性?

3 个答案:

答案 0 :(得分:4)

试试这个:

SELECT PersonID, SizeName
FROM
   (
   SELECT
      PersonID,
      (SELECT MAX([LowerLimit]) FROM dbo.[Size] WHERE [LowerLimit] < [COUNT]) As LowerLimit
   FROM dbo.Person
   ) A
   INNER JOIN dbo.[SIZE] B ON A.LowerLimit = B.LowerLimit

答案 1 :(得分:1)

With Ranges As
    (
    Select 'Small' As Name, 0 As LowerLimit
    Union All Select 'Medium', 50
    Union All Select 'Large', 100
    )
    , Person As
    (
    Select 1 As PersonId, 45 As [Count]
    Union All Select 2, 5
    Union All Select 3, 120
    Union All Select 4, 87
    Union All Select 5, 60
    Union All Select 6, 200
    Union All Select 7, 31
    )
    , RangeStartEnd As
    (
    Select R1.Name
        , Case When Min(R1.LowerLimit) = 0 Then -1 Else MIN(R1.LowerLimit) End As StartValue
        , Coalesce(MIN(R2.LowerLimit), 2147483647) As EndValue
    From Ranges As R1
        Left Join Ranges As R2
            On R2.LowerLimit > R1.LowerLimit
    Group By R1.Name
    )
Select P.PersonId, P.[Count], RSE.Name
From Person As P
    Join RangeStartEnd As RSE
        On P.[Count] > RSE.StartValue 
            And P.[Count] <= RSE.EndValue

虽然我使用只存在于SQL Server 2005+中的公用表表达式(简称cte),但这可以通过多个查询完成,您可以在其中创建临时表来存储等效的RangeStartEnd CTE。诀窍是创建一个具有开始列和结束列的视图。

答案 2 :(得分:1)

SELECT p.PersonID, Ranges.SizeName
FROM People P
JOIN
    (
    SELECT SizeName, LowerLimit, MIN(COALESCE(upperlimit, 2000000)) AS upperlimit
    FROM (
        SELECT rl.SizeName, rl.LowerLimit, ru.LowerLimit AS UpperLimit
        FROM Ranges rl
        LEFT OUTER JOIN Ranges ru ON rl.LowerLimit < ru.LowerLimit
        ) r
    WHERE r.LowerLimit < COALESCE(r.UpperLimit, 2000000)
    GROUP BY SizeName, LowerLimit
    ) Ranges ON p.Count >= Ranges.LowerLimit AND p.Count < Ranges.upperlimit
ORDER BY PersonID