Comment find la plage d'un nombre où les plages viennent dyamically d'une autre table?

Si j'avais deux tables:

PersonID | Count ----------------- 1 | 45 2 | 5 3 | 120 4 | 87 5 | 60 6 | 200 7 | 31 SizeName | LowerLimit ----------------- Small | 0 Medium | 50 Large | 100 

J'essaie de comprendre comment faire une requête pour get un résultat similaire à:

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

Fondamentalement, une table spécifie un nombre inconnu de "noms de plage" et leurs plages entières associées. Ainsi, une plage de comptage de 0 à 49 dans la table des personnes obtient une «petite» désignation. 50-99 obtient 'moyen', etc. Mais j'ai besoin d'être dynamic parce que je ne connais pas les noms de plage ou les valeurs entières. Puis-je le faire en une seule requête ou devrais-je écrire une fonction séparée pour parcourir les possibilités?

Essayez ceci:

 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 
 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 

Bien que j'utilise des expressions de table commune (cte pour faire court) qui existent uniquement dans SQL Server 2005+, cela peut être fait avec plusieurs requêtes où vous créez une table temporaire pour stocker l'équivalent du cte RangeStartEnd . L'astuce consiste à créer une vue qui a une colonne de début et une colonne de fin.

 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