2012-03-12 17 views
0

これはフォローアップの質問os thisです。他の人は重要な部分(どのようにパーティションによってSUMに答えます)私はそれを受け入れています。しかし、別の部分は私を心配しています。多対多リレーションシップを持つDistinct SUM

「左」側を1回だけカウントする必要がある場合は、多対多の関係での方法は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の違い

は、うまくいけば私の問題を説明し、次のサンプルデータを考えてみましょう。 relation-tableの最後のエントリはすでに別のT2(aaa)に割り当てられていたbbbにT1を挿入するため、T2-グループの名前はaaaですでにT1SumPriceになっています。

それで、すでに別のグループの一部である場合に値を2回カウントするのを防ぐにはどうすればよいですか?

編集

これは、(実際にテーブル値関数の一部である)Nikola's answerから得られたクエリです。私は値を取得するスカラー値関数を使用する必要があることに注意してください:

select T2.idSparePart As T2_ID 
,T2.PartNumber as T2_PartNumber 
,Gambio.getGoodsIn(T2.idSparePart,@FromDate,@ToDate) AS GoodsIn 
,Gambio.getOrdered(T2.idSparePart,@FromDate,@ToDate) AS Ordered 
,T1Sum.ClaimedReused As T1SumPrice_ClaimedReused 
,T1Sum.Costsaving As T1SumPrice_Costsaving 
,T1.Price As T1HighestPrice 
,T1.idSparePart AS T1HighestPrice_ID 
,T1.SparePartName As T1HighestPrice_Number 
,T1.SparePartDescription As T1HighestPrice_Name 
,Cat.SparePartCategoryName As T1HighestPrice_Category 
FROM Gambio.SparePart T2 
INNER JOIN (
    SELECT Rel.fiSparePart 
     ,Rel.fiTabSparePart 
     ,ROW_NUMBER()OVER(Partition By Rel.fiSparePart Order By Price DESC)As PriceList 
     ,SUM(Gambio.getMaterialQuantity(Rel.fiTabSparePart,NULL,NULL,@idClaimStatus,1))OVER(PARTITION BY Rel.fiSparePart) AS ClaimedReused 
     ,SUM(Gambio.getCostSaving(Rel.fiTabSparePart,NULL,NULL,@idClaimStatus))OVER(PARTITION BY Rel.fiSparePart) AS Costsaving 
     FROM tabSparePart T1 
     INNER JOIN 
      (select fiTabSparePart 
      , fiSparePart 
      from Gambio.trelSparePartClaimGroup relation 
      where not exists (
       select null 
       from Gambio.trelSparePartClaimGroup rel 
       where rel.fiTabSparePart = relation.fiTabSparePart 
       and rel.fiSparePart < relation.fiSparePart 
      ) 
     ) 
     Rel ON Rel.fiTabSparePart=T1.idSparePart 
)AS T1Sum ON T1Sum.fiSparePart = T2.idSparePart AND t1Sum.PriceList = 1 
INNER JOIN tabSparePart T1 ON T1Sum.fiTabSparePart=T1.idSparePart 
INNER JOIN tabSparePartCategory AS Cat 
    ON Cat.idSparePartCategory=T1.fiSparePartCategory 

残念ながら、私が間違った結果を行うための

+0

どのようにt1行の値を複数のグループの共通メンバーであるt2グループに分割したいですか?与えられた例では、t1.ID 2はt2.ID 1と2のメンバーです(つまり 'aaa'と' bbb') - その値を 'aaa'に完全に代入したいと思っていますが、そのための根底にある論理についての説明はありません。 –

+4

希望の結果のT1Sum価格が150ではなく100であってはなりませんか? – GarethD

+0

@マーク:問題はそのような論理がないということです。唯一防止すべきことは、「T1価格」が何度も数えられることです。最後に、これらの値は別の 'Group By T1Category'の下に含まれます。だから私は正しい順序カウント(合計されていない)と私はグループ化するために使用することができる1つの関連するT1行ですべての別個のT2行を取得することを確認する必要があります。 –

答えて

3

方法を取得するように、いくつかのT1-レコードをスキップしているようですつまり、最初のものを除くすべてが省略されるように関係をフィルタリングすることです。あなたの例を正しく読んだら、T1SumPriceはbbb行の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を使っていて、@を取り除かなければならなかった。

EDIT:解説してください。

サブクエリrelによってt2関係の1つのみが許可されているため、これは機能します。私は最初のIDを選択しますが、これはユースケースによって異なります。他の人が言っているように、他のオプション、均等または比例配分があります。

+0

ありがとうございます。 @をもう一度追加したら、それは動作します。しかし、私は理由は分かりません;)だから私はあなたのアプローチを理解し、それが適用可能かどうかを見て時間が必要です。 –

+0

ようこそ。私は私の答えを編集しました。 –

1

質問は、私は次のようなアプローチを提供して重複をelimateするために実装するためのルールまさに明らかではないとして:

;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 

それが返されます例えばので、これが均等に重複関係を通して価格を配布します。

SUM列ではなく、MAX列全体で案分へ
T2Name T2Orders T1SumPrice T1HighestPrice T1HighestPrice_Name 
aaa   25   275,00   200,00   AAA 
bbb   35   175,00   150,00   BBB 
+0

これは興味深いアプローチです。私はまずあなたが平均をどのようにしているのか、それが可能な割り当てに当てはまるのかを最初に理解する必要があります。しかし、事前にお時間をいただき、ありがとうございます。 –

+0

クエリは、各T1IDが@RELATIONの 'COUNT(*)OVER(PARTITION BY t1ID)'に表示される回数をカウントします(行8)。@ t1の価格を@Relationsに表示される回数t1IDで割り、これを価格とする(4行目と5行目)。 – GarethD

2

T1の価格、以下を試してみてください。

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 
関連する問題