Как найти диапазон числа, где диапазоны берутся динамически из другой таблицы? - PullRequest
2 голосов
/ 24 августа 2010

Если бы у меня было две таблицы:

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 ]

4 голосов
/ 24 августа 2010

Попробуйте это:

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 голос
/ 24 августа 2010
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
1 голос
/ 24 августа 2010
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

Хотя я использую выражения общих таблиц (cte для краткости), которые существуют только в SQL Server 2005+, это можно сделать с помощью нескольких запросов, когда вы создаете временную таблицу для хранения эквивалента RangeStartEnd cte.Хитрость заключается в том, чтобы создать представление с начальным и конечным столбцами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...