2017-08-11 13 views
0

データベースに4つのテーブルがあります。倉庫にはクライアントが所有する箱があり、ボックスにはファイルがあります。 Clientテーブル、Warehouseテーブル、Boxesテーブル、およびFilesテーブルがあります。JOINを使用した3つのテーブルのSQLカウント

のでClientテーブルを外部キーとしてWarehouseIDがあり、Boxesテーブルには外部キーとしてClientIDを持ち、Filesテーブルは外部キーとしてBoxIDを持っています。私は、各クライアントがクエリで持っているボックスとファイルの数と、倉庫の内外にあるボックスの数を数えたいと思います。 BoxesおよびFilesテーブルのStatusフィールドは、ボックスとファイルが倉庫の中または外にあるかどうかを決定します。私は、ボックスに次のクエリを実行し、数字が正しい:回数の出力が正しい

ClientID | ClientName | WarehouseName | BoxCount | BoxesIn | BoxesOut | BoxesForDestruction 
1  | ACME Corp. | FooFactory | 22744 | 22699 | 45  | 7888 

SELECT 
    [c].[ClientID], 
    [c].[Name] AS [ClientName], 
    [w].[Name] AS [WarehouseName], 
    COUNT(DISTINCT [b].[BoxID]) AS [BoxCount], 
    SUM(CASE WHEN [b].[Status] = @IN THEN 1 ELSE 0 END)) AS [BoxesIn], 
    SUM(CASE WHEN [b].[Status] = @OUT THEN 1 ELSE 0 END) AS [BoxesOut], 
    SUM(CASE WHEN [b].[DestructionDate] <= GETDATE() THEN 1 ELSE 0 END) AS [BoxesForDestruction], 
FROM [Clients] AS [c] INNER JOIN [Boxes] AS [b] 
    ON [c].[ClientID] = [b].[ClientID] 
INNER JOIN [Warehouses] AS [w] 
    ON [c].WarehouseID = [w].[WarehouseID] 
WHERE [c].[ClientID] = @ClientID 
GROUP BY 
    [c].[ClientID], 
    [c].[Name], 
    [w].[Name] 

これはの出力を生成します。 FilesテーブルをINNER JOINに追加すると、数字が膨らんでしまいます。ここではSQLは次のとおりです。

SELECT 
    [c].[ClientID], 
    [c].[Name] AS [ClientName], 
    [w].[Name] AS [WarehouseName], 
    COUNT(DISTINCT [b].[BoxID]) AS [BoxCount], 
    COUNT(DISTINCT [f].[FileID]) AS [FileCount], -- *NEW* 
    SUM(CASE WHEN [b].[Status] = @IN THEN 1 ELSE 0 END)) AS [BoxesIn], 
    SUM(CASE WHEN [b].[Status] = @OUT THEN 1 ELSE 0 END) AS [BoxesOut], 
    SUM(CASE WHEN [b].[DestructionDate] <= GETDATE() THEN 1 ELSE 0 END) AS [BoxesForDestruction], 
FROM [Clients] AS [c] INNER JOIN [Boxes] AS [b] 
    ON [c].[ClientID] = [b].[ClientID] 
INNER JOIN [Warehouses] AS [w] 
    ON [c].[WarehouseID] = [w].[WarehouseID] 
INNER JOIN [Files] AS [f]  -- *NEW* 
    ON [b].[BoxID] = [f].[BoxID] -- *NEW* 
WHERE [c].[ClientID] = @ClientID 
GROUP BY 
    [c].[ClientID], 
    [c].[Name], 
    [w].[Name] 

これは私に(彼らは関連していないですので、私は最初の3列を省略しました)以下のカウント出力を与える:

BoxCount | FilesCount | BoxesIn | BoxesOut | BoxesForDestruction 
19151 | 411961  | 411381 | 580  | 144615  

FilesCountは正しいのですが、他の数字はオフです。私はなぜこれが起こっているのか知っていますが、私はそれを修正する方法がわかりません。追加の行は、ボックスとファイルの結合によって返された複数の行のために作成されます。 SUMを実行すると、余分な行がカウントを膨らませます。ウェアハウスの行は1つだけなので、その結合はカウントに影響しません。倉庫に出入りするファイルとボックスの正しい数を取得するためにクエリを変更するにはどうすればよいですか?

答えて

1

joinは、右側の表の各行について左側の表の各行を繰り返します。複数の結合を結合すると、いくつかの行が二重にカウントされます。解決策は、カウントをサブクエリに移動することです。例:

select * 
from table1 t1 
join (
     select table1_id 
     ,  count(*) 
     from table2 
     group by 
       table1_id 
     ) t2 
on  t2.table1_id = t1.id 
join (
     select table1_id 
     ,  count(*) 
     from table3 
     group by 
       table1_id 
     ) t3 
on  t3.table1_id = t1.id 
+0

これは完璧に、ありがとうございました。 – Nse

関連する問題