这是一个后续问题os this。由于另一个回答了一个重要的部分(如何通过分区SUM
)我保持接受。但另一部分让我担心。
如果“左”方只计算一次,如何在多对多关系中SUM
。
考虑以下样本数据,希望能够解释我的问题:
declare @t1 table (ID int,Price money, Name varchar(10))
declare @t2 table (ID int,Orders int, Name varchar(10))
declare @relation table (t1ID int,t2ID int)
insert into @t1 values(1, 200, 'AAA');
insert into @t1 values(2, 150, 'BBB');
insert into @t1 values(3, 100, 'CCC');
insert into @t2 values(1,25,'aaa');
insert into @t2 values(2,35,'bbb');
insert into @relation values(1,1);
insert into @relation values(2,1);
insert into @relation values(3,2);
-- following record will cause the "wrong" sum
insert into @relation values(2,2);
select
T2.Name as T2Name
,T2.Orders As T2Orders
,T1Sum.Price As T1SumPrice
,T1.Price As T1HighestPrice
,T1.Name As T1HighestPrice_Name
FROM @t2 T2
INNER JOIN (
SELECT Rel.t2ID
,Rel.t1ID
,ROW_NUMBER()OVER(Partition By Rel.t2ID Order By Price DESC)As PriceList
,SUM(Price)OVER(PARTITION BY Rel.t2ID) AS Price
FROM @t1 T1
INNER JOIN @relation Rel ON Rel.t1ID=T1.ID
)AS T1Sum ON T1Sum.t2ID = T2.ID AND t1Sum.PriceList = 1
INNER JOIN @t1 T1 ON T1Sum.t1ID=T1.ID
实际结果:
T2Name T2Orders T1SumPrice T1HighestPrice T1HighestPrice_Name
aaa 25 350,00 200,00 AAA
bbb 35 250,00 150,00 BBB
期望的结果:
T2Name T2Orders T1SumPrice T1HighestPrice T1HighestPrice_Name
aaa 25 350,00 200,00 AAA
bbb 35 100,00 150,00 BBB
注意T1SumPrice
的区别。关系表中的最后一个条目将T1添加到已分配给另一个T2(bbb
)的aaa
,因此它已经是{-1}}的一部分,其中T2-group的名称为{ {1}}。
那么,当他们已经是另一组的一部分时,我怎么能防止计数值两次呢?
修改:
这是来自Nikola's answer的结果查询(实际上是表值函数的一部分)。请注意,我需要使用标量值函数来检索值:
T1SumPrice
不幸的是,它似乎跳过了一些T1记录,因此我得到了错误的结果
答案 0 :(得分:3)
这样做的方法是过滤关系,以便除了第一个之外的所有关系。如果我正确地读了你的例子,对于bbb行,T1SumPrice应该是100,00,因为从关系你可以看出t2id = 1你总和200 + 150,而t2id = 2 100 + 150但是150已经花费在前一行。
select
T2.Name as T2Name
,T2.Orders As T2Orders
,T1Sum.Price As T1SumPrice
,T1.Price As T1HighestPrice
,T1.Name As T1HighestPrice_Name
FROM t2 T2
INNER JOIN (
SELECT Rel.t2ID
,Rel.t1ID
,ROW_NUMBER()OVER(Partition By Rel.t2ID Order By Price DESC)As PriceList
,SUM(Price)OVER(PARTITION BY Rel.t2ID) AS Price
FROM t1 T1
INNER JOIN
(select t1id, t2id
from Relation
where not exists (select null from relation test where test.t1id = relation.t1id
and test.t2id < relation.t2id)
)
Rel ON Rel.t1ID=T1.ID
)AS T1Sum ON T1Sum.t2ID = T2.ID AND t1Sum.PriceList = 1
INNER JOIN t1 T1 ON T1Sum.t1ID=T1.ID
P.S。我正在使用Sql Fiddle并且不得不摆脱@。
编辑:尝试解释。
这是有效的,因为子查询 rel 只允许t2关系中的一个。我选择第一个id,但这取决于你的用例。正如其他人所说,还有其他选择,即相等或按比例分配。
答案 1 :(得分:2)
要在SUM列中提供T1价格而不是MAX列,请尝试以下操作:
select
MAX(T2.Name) as T2Name
,MAX(T2.Orders) As T2Orders
,SUM(T1Sum.ProRataPrice) As T1SumPrice
,MAX(T1Sum.Price) As T1HighestPrice
,MAX(CASE WHEN PriceList=1 THEN T1Sum.Name END) As T1HighestPrice_Name
FROM @t2 T2
INNER JOIN (
SELECT Rel.t2ID
,Rel.t1ID
,Name
,ROW_NUMBER()OVER(Partition By Rel.t2ID Order By Price DESC)As PriceList
,Price
,Price / COUNT(*)OVER(PARTITION BY Rel.t1ID) AS ProRataPrice
FROM @t1 T1
INNER JOIN @relation Rel ON Rel.t1ID=T1.ID
)AS T1Sum ON T1Sum.t2ID = T2.ID
GROUP BY T2.ID
答案 2 :(得分:1)
由于问题不清楚究竟要实施什么规则来强制重复,我提供了以下方法:
;WITH T1Sum AS
( SELECT Rel.t2ID,
Rel.t1ID,
ROW_NUMBER() OVER(PARTITION BY Rel.t2ID ORDER BY Price / Relations DESC) As PriceList,
SUM(Price / Relations) OVER (PARTITION BY t2ID) [Price]
FROM @t1 T1
INNER JOIN
( SELECT *,COUNT(*) OVER(PARTITION BY t1ID) [Relations]
FROM @Relation
) rel
ON Rel.t1ID = T1.ID
)
SELECT T2.Name as T2Name,
T2.Orders As T2Orders,
T1Sum.Price As T1SumPrice,
T1.Price As T1HighestPrice,
T1.Name As T1HighestPrice_Name
FROM @t2 T2
INNER JOIN T1Sum
ON T1Sum.t2ID = T2.ID
AND t1Sum.PriceList = 1
INNER JOIN @t1 T1
ON T1Sum.t1ID = T1.ID
这将通过重复关系均匀分配价格,因此对于示例,它将返回:
T2Name T2Orders T1SumPrice T1HighestPrice T1HighestPrice_Name
aaa 25 275,00 200,00 AAA
bbb 35 175,00 150,00 BBB