我有一个递归选择问题,我无法工作,感觉就像在那里,但不一定。
我有两张表:
List ProductCode SortNumber
------------------------------------
1 A 1
1 B 2
1 F 3
1 G 4
1 K 5
2 C 1
2 A 2
3 B 1
3 K 2
3 G 3
ProductType Client ProductCode Price
---------------------------------------------------
Type 1 1 A 100
Type 1 1 A 150
Type 1 1 B 200
Type 1 1 B 120
Type 1 1 F 150
Type 2 1 A 200
Type 2 1 A 300
Type 2 1 B 300
Type 2 1 F 400
Type 2 1 G 125
Type 2 1 G 75
Type 1 2 A 190
Type 1 2 A 130
Type 1 2 A 200
Type 1 2 B 270
Type 1 2 B 180
Type 1 2 F 130
Type 2 2 A 210
Type 2 2 A 100
Type 2 2 B 350
Type 2 2 F 200
Type 2 2 G 175
Type 2 2 G 95
Type 2 2 K 65
我想要实现的是当我要求产品列表为1时,它将获得与产品代码相关的所有最高价格。如果产品类型1没有价格,它将检查产品类型2的最高价格。如果没有相应的类型2价格,则值为0.
因此,所需的输出是当我为所有客户请求价格表1时(比如客户1和2),所需的输出应为
Client ProductCode SortNumber PriceToDisplay
---------------------------------------------------
1 A 1 150
1 B 2 200
1 F 3 150
1 G 4 125 (No Type 1, so we get type 2 price)
1 K 5 0 (No Type 1, 2 Price for Product K)
2 A 1 200
2 B 2 270
2 F 3 130
2 G 4 175
2 K 5 65
由于我的印象是这可能是一个递归选择,我想到了使用CTE。我有这个查询 -
(请注意评论代码 - - 和pp1.ProductCode = pp2.ProductCode )
Declare @List int = 1
;With ClientCTE As (
Select Distinct Client From ClientsTable
),
RecursiveSelect As (
Select p1.Client
, l.ProductCode
, l.SortOrder
, p1.Price As P1Price
, p2.Price As P2Price
, Case when p1.Price Is Null Then Case When p2.Price Is Null Then 0 Else p2.Price End
Else p1.Price End As PriceToDisplay
From ProductList l
Left Join (
Select Distinct pp.Client, pp.ProductCode, Max(pp.Price) As ItemPrice From ProductPrice pp
Left Join ClientCTE c On c.Client = pp.Client
Where pp.ProductType = 1
Group By pp.Client, pp.ProductCode) p1 On p1.ProductCode = l.ProductCode
Left Join (
Select Distinct pp.Client, pp.ProductCode, Max(pp.Price) As ItemPrice From ProductPrice pp
Left Join ClientCTE c On c.Client = pp.Client
Where pp.ProductType = 2
Group By pp.Client, pp.ProductCode) p2 On p2.Client = p1.Client
Where pp1.Client = pp2.Client
-- And pp1.ProductCode = pp2.ProductCode **this commented code**
And l.List = 1
)
Select Distinct Client, ProductCode, SortOrder, Max(P1Price), Max(P2Price)
From RecursiveSelect
Group By Client, ProductCode, SortOrder
调查结果 - CTE
如果代码被注释,它将:
结果
Client ProductCode SortNumber PriceToDisplay
---------------------------------------------------
1 A 1 150
1 B 2 200
1 F 3 150
(missing G and K product codes)
2 A 1 200
2 B 2 270
2 F 3 130
2 G 4 175
2 K 5 65
如果没有注释代码,它将:
结果
Client ProductCode SortNumber PriceToDisplay
---------------------------------------------------
1 A 1 WRONG PRICE
1 B 2 WRONG PRICE
1 F 3 WRONG PRICE
1 G 4 WRONG PRICE
1 K 5 WRONG PRICE
2 A 1 WRONG PRICE
2 B 2 WRONG PRICE
2 F 3 WRONG PRICE
2 G 4 WRONG PRICE
2 K 5 WRONG PRICE
我想我的查询只需要进行一次调整,但我无法准确指出确切的位置。未注释的代码返回正确的值,但为什么它不返回丢失的左表值,因为它是左连接?
答案 0 :(得分:0)
您可以使用OUTER APPLY
获取最高价格,您不需要递归CTE
select c.Client, l.ProductCode, l.SortNumber, Price = isnull(p.Price, 0)
from ProductList l
cross join ClientCTE c
outer apply
(
-- Top 1 to return only one row per client + Pproduct Code
select top 1 p.Price
from ProductPrice p
where p.Client = c.Client
and p.ProductCode = l.ProductCode
-- Type 1 will comes before Type 2, and higher price first
-- If there isn't any rows for Type 1, Type 2 will be selected
-- no rows return if no rows are found
order by p.ProductType, p.Price desc
) p
where l.List = 1
order by Client, ProductCode
答案 1 :(得分:0)
您可以通过
加入和分组来完成此操作declare @PL table (client int, ProductCode char(1), Sort int);
insert into @pl values
(1, 'A', 1),
(1, 'B', 2),
(1, 'F', 3),
(1, 'G', 4),
(1, 'K', 5),
(2, 'C', 1),
(2, 'A', 2),
(3, 'B', 1),
(3, 'K', 2),
(3, 'G', 3);
--select * from @PL;
declare @PP table (ProductType varchar(10), Client int, ProductCode char(1), Price int);
insert into @PP values
('Type 1', 1, 'A', 100),
('Type 1', 1, 'A', 150),
('Type 1', 1, 'B', 200),
('Type 1', 1, 'B', 120),
('Type 1', 1, 'F', 150),
('Type 2', 1, 'A', 200),
('Type 2', 1, 'A', 300),
('Type 2', 1, 'B', 300),
('Type 2', 1, 'F', 400),
('Type 2', 1, 'G', 125),
('Type 2', 1, 'G', 75),
('Type 1', 2, 'A', 190),
('Type 1', 2, 'A', 130),
('Type 1', 2, 'A', 200),
('Type 1', 2, 'B', 270),
('Type 1', 2, 'B', 180),
('Type 1', 2, 'F', 130),
('Type 2', 2, 'A', 210),
('Type 2', 2, 'A', 100),
('Type 2', 2, 'B', 350),
('Type 2', 2, 'F', 200),
('Type 2', 2, 'G', 175),
('Type 2', 2, 'G', 95),
('Type 2', 2, 'K', 65);
--select * from @pp;
select pl.client, pl.ProductCode
--, pp1.Price as Price1, pp2.Price as Price2
, max(isnull(pp1.Price, isnull(pp2.Price, 0))) as Price12
from @PL pl
left join @PP pp1
on pp1.ProductCode = pl.ProductCode
and pp1.Client = pl.client
and pp1.ProductType = 'Type 1'
left join @PP pp2
on pp2.ProductCode = pl.ProductCode
and pp2.Client = pl.client
and pp2.ProductType = 'Type 2'
where pl.client in (1, 2)
group by pl.client, pl.ProductCode
order by pl.client, pl.ProductCode;
答案 2 :(得分:0)
根据要求,这就是我要做的。
子查询或视图,例如vw_product_max_price
:
select producttype, client, productcode, max(price) as maxprice group by producttype, client, productcode
查询请求产品清单
select MP.client, MP.productcode, PL.sortnumber,
case MP.maxprice
when NULL
then 0
else MP.maxprice
end as PriceToDisplay
from productlist PL left outer join vw_product_max_price MP on PL.productcode=MP.productcode
where MP.client = ? and MP.productcode = ?
我没有对此进行过测试..但我们的想法是首先列出每个产品代码的最高价格。
答案 3 :(得分:0)
所以我和一位朋友坐在一起工作。有效的解决方案(从原始数据库表名和列调整)如下:
Declare @List int = 1
;With ClientCTE (BuyGroup, CustomerPriceGroup, ProductListHeaderId) As (
Select Distinct Client From ClientsTable
),
RecursiveSelect As (
Select x.Client, x.ProductCode
, Case When Max(Type1Price) Is Null Then
Case When Max(Type2Price) Is Null Then 0
Else Max(Type2Price) End
Else Max(Type1Price) End
As PriceToDisplay
From
(Select h.Client, h.ProductCode,
Case When h.ProductType = 'Type1'
Then
Max(h.UnitPrice)
Else
Null
End As Type1Price
, Case When h.ProductType = 'Type2'
Then
Max(h.UnitPrice)
Else
Null
End As Type2Price
, h.BuyGroup, h.ConditionScale
From ProductPrice h
Inner Join ClientCTE c On c.Client = h.Client
Where
h.ProductType In ('Type1', 'Type2')
And h.ProductCode In (Select ProductCode From ProductList where List = @List)
Group by h.Client, h.ProductCode
) x
Group by Client, ProductCode
)
select * from RecursiveSelect
我们都发现在原始查询中,两个左连接只有一个条件(即ProductType)不同。一旦我们从查询中获得原始数据,我们就会分组并选择将要显示的价格。
CTE的原因是查询的初衷是获取N个客户的价格。这就是锚定查询获取客户端列表然后传递给第二个客户端列表的原因。此外,如果你也在处理X个列表,你可以在锚点查询中包含它并替换" @ List"与第一个列。