Sohail Hameed
Sohail Hameed

Reputation: 988

Sql Query to return following result set

I have two tables [Price Range]

ID |   Price
1  |   10
2  |   50
3  |   100

and Product:

ID | Name  |  Price
1  | Prod1 |  5
2  | Prod2 |  10
3  | Prod3 |  20
4  | Prod4 |  30
5  | Prod5 |  50
6  | Prod5 |  60
7  | Prod6 |  120

I need to associate product with specific price range i.e. join both table by price range and require result set like this:

ProductPriceRange

ID | Name  |  Price | PriceRangeID
1  | Prod1 |  5     | Null
2  | Prod2 |  10    | 1
3  | Prod3 |  20    | 1
4  | Prod4 |  30    | 1
5  | Prod5 |  50    | 2
6  | Prod5 |  60    | 2
7  | Prod6 |  120   | 3

Upvotes: 0

Views: 112

Answers (4)

gofr1
gofr1

Reputation: 15977

If Price Range ID's are ascending as price then you can simple:

SELECT  p.ID,
        p.Name,
        MAX(pr.ID) as PriceRangeID
FROM Product p
LEFT JOIN PriceRange pr 
    ON p.Price >= pr.Price
GROUP BY p.ID, p.Name

Output:

ID          Name  PriceRangeID
----------- ----- ------------
1           Prod1 NULL
2           Prod2 1
3           Prod3 1
4           Prod4 1
5           Prod5 2
6           Prod5 2
7           Prod6 3
Warning: Null value is eliminated by an aggregate or other SET operation.

(7 row(s) affected)

Another way with new cte:

;WITH new_price_range AS (
SELECT  pr1.ID,
        MAX(pr1.Price) as PriceB,
        MIN(ISNULL(pr2.Price-1,pr1.Price*10)) as PriceT 
FROM PriceRange pr1
LEFT JOIN PriceRange pr2 
    ON Pr1.Price < Pr2.Price
GROUP BY pr1.ID)

SELECT  p.ID,
        p.Name,
        pr.ID as PriceRangeID
FROM Product p
LEFT JOIN new_price_range pr 
    ON p.Price between pr.PriceB and pr.PriceT

In this cte we generate this:

ID          PriceB      PriceT
----------- ----------- -----------
1           10          49
2           50          99
3           100         1000

(3 row(s) affected)

Output:

ID          Name  PriceRangeID
----------- ----- ------------
1           Prod1 NULL
2           Prod2 1
3           Prod3 1
4           Prod4 1
5           Prod5 2
6           Prod5 2
7           Prod6 3

(7 row(s) affected)

Upvotes: 0

Jaydip Jadhav
Jaydip Jadhav

Reputation: 12309

Use Outer Apply

SELECT  p.ID,
        p.Name,
        p.Price,
        PriceRangeTable.ID as PriceRangeID
FROM Product p
OUTER APPY(
SELECT TOP(1) ID
FROM PriceRange pr 
WHERE p.Price >= pr.Price)PriceRangeTable

Upvotes: 1

cha
cha

Reputation: 10411

Another way of doing this is by building a ranges CTE with the PriceFrom/PriceTo columns, like this:

with rangesWithRn as (
    select [ID], [Price],
    ROW_NUMBER() OVER(ORDER BY [Price]) as rn
    FROM #PriceRange),
ranges as (
    select r1.ID, r1.Price as PriceFrom, COALESCE(r2.Price, 2147483647) as PriceTo
    FROM rangesWithRn r1 LEFT JOIN rangesWithRn r2
    ON r2.rn = r1.rn + 1
)
SELECT p.[ID], p.[Name], p.[Price], r.[ID]
from #Product p LEFT JOIN ranges r 
   ON p.Price >= r.PriceFrom and p.Price < r.PriceTo

Result:

ID          Name  Price       ID
----------- ----- ----------- -----------
1           Prod1 5           NULL
2           Prod2 10          1
3           Prod3 20          1
4           Prod4 30          1
5           Prod5 50          2
6           Prod5 60          2
7           Prod6 120         3

(7 row(s) affected)

Upvotes: 2

Pham X. Bach
Pham X. Bach

Reputation: 5442

You can use this

select id, name, price, 
    (select id 
     from PriceRange
     where price = (select max(price) 
                   from PriceRange 
                   where price <= a.price)
    ) as PriceRangeID 
from Product a

Upvotes: 2

Related Questions