0

Project、Equipment、Fish、Staff の 6 つのテーブルと、Project_Equipment、Project_Fish、および Project_Staff のジャンクション テーブルがあります。プロジェクトの総コストを取得したいと考えています。
というわけで、以下のような文を書きました。

SELECT P.ProjectID, (SUM(E.EquipPrice*PE.EQuantity)+SUM(F.FishPrice*PF.FQuantity)+SUM(PS.Salary)) as ProjectCost  
FROM Equipment as E INNER JOIN Project_Equipment as PE  
ON E.EquipID=PE.EquipID  
INNER JOIN Project as P  
ON PE.ProjectID=P.ProjectID  
INNER JOIN Project_Fish as PF  
ON P.ProjectID=PF.ProjectID  
INNER JOIN Fish as F  
ON PF.FishID=F.FishID  
INNER JOIN Project_Staff as PS  
ON P.ProjectID=PS.ProjectID  
INNER JOIN Staff as S
PS.StaffID=S.StaffID  
GROUP BY ProjectID  

しかし、私は正しい金額の 2 倍の価格を取得しました。

4

1 に答える 1

0

クエリは多くの重複した結果になります。次のより単純なケースを考えてみましょう。

Table: Project
ProjectID  EQuantity
  1          1
  2          1

Table: Equipment
EquipID    EPrice
  1          1
  2          1

Table: Fish
FishID
  1
  2

Table: Project_Equipment
ProjectID  EquipID
  1          1
  1          2
  2          1
  2          2

Table: Project_Fish
ProjectID  FishID
  1          1 
  1          2
  2          1
  2          2

Project_Equipmentここで、クエリの結果のみを見てみましょう。

SELECT p.projectid, e.eprice, pe.equantity FROM project p
INNER JOIN project_equipment pe ON pe.projectid=p.projectid
INNER JOIN equipment e ON e.equipid=pe.equipid

ProjectID EPrice EQuantity
1    1    1   // a
1    1    1   // b
2    1    1   // c
2    1    1   // d

それは予想通りです。各プロジェクトで使用される各機器の価格と数量のリスト。INNER JOIN しかし、私たちがそうするとき、何が起こると思いますproject_fishか? その最初の結果にはプロジェクト 1 が 2 回含まれており、プロジェクト 2 が 2 回含まれているため、その結果とproject_fish!のすべての組み合わせになります。

SELECT p.projectid, e.eprice, pe.equantity, f.fishid FROM project p
INNER JOIN project_equipment pe ON pe.projectid=p.projectid
INNER JOIN equipment e ON e.equipid=pe.equipid
INNER JOIN project_fish pf ON pf.projectid=p.projectid

ProjectID EPrice EQuantity FishID
1    1    1    1   // from a above
1    1    1    2   // from a above
1    1    1    1   // from b above 
1    1    1    2   // from b above
2    1    1    1   // from c above
2    1    1    2   // from c above
2    1    1    1   // from d above
2    1    1    2   // from d above

この複製は、すべての内部結合で続行されます。割引額は常に 2 倍になるとは限りません。実際には、すべての結合の組み合わせの数によって異なります。

したがって、この特定のクエリでやろうとしていることを実際に行うことはできません。代わりに、各関係のコストを個別に計算する必要があります。次に、それらすべてを合計します。ProjectIDこれを行うには、それぞれを個別に選択し、コストをandProjectCost列に計算し、 を使用UNIONしてそれらを連結し、再度結果をグループ化して個々の小計ProjectIDを合計します。ProjectCost

下手に説明しましたが、設備、魚、給与の小計を 1 つの表にまとめて合計すると考えてください。例えば:

SELECT x.projectid, SUM(x.ProjectCost) FROM 
(
    SELECT p.projectid, SUM(e.eprice * pe.equantity) ProjectCost FROM project p
    INNER JOIN project_equipment pe ON pe.projectid=p.projectid
    INNER JOIN equipment e ON e.equipid=pe.equipid
    GROUP BY p.projectid
  UNION
    SELECT p.projectid, SUM(f.fprice * pf.fquantity) ProjectCost FROM project p
    INNER JOIN project_fish pf ON pf.projectid=p.projectid
    INNER JOIN fish f ON f.fishid=pf.fishid
    GROUP BY p.projectid
  UNION
    SELECT p.projectid, SUM(s.salary) ProjectCost FROM project p
    INNER JOIN project_staff ps ON ps.staffid=p.projectid
    INNER JOIN staff s ON s.staffid=ps.staffid
    GROUP BY p.projectid
) x
GROUP BY x.projectid

各サブクエリは、projectid列と列を生成しProjectCostます。サブクエリ (括弧の間) を単独で実行して、結果を確認します。外側のクエリは、プロジェクトの小計を追加します。

申し訳ありませんが、テスト中に EquipPrice 列と FishPrice 列の名前を EPrice と FPrice に変更しました。

于 2013-08-14T01:58:00.560 に答える