Reputation: 988
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
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
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
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
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