Sql Query返回以下结果集

时间:2016-04-22 06:41:57

标签: sql sql-server

我有两张表[Price Range]

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

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

我需要将产品与特定价格范围相关联,即按价格范围加入两个表格并要求结果设置如下:

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

4 个答案:

答案 0 :(得分:2)

您可以使用此

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

答案 1 :(得分:2)

另一种方法是使用PriceFrom / PriceTo列构建ranges CTE,如下所示:

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

结果:

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)

答案 2 :(得分:1)

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

答案 3 :(得分:0)

如果Price Range ID以价格递增,那么您可以简单:

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

输出:

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)

新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

在这个cte中我们生成了这个:

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

(3 row(s) affected)

输出:

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)