2017-08-11 275 views
0

我在數據庫中有4個表。倉庫包含客戶擁有的箱子,箱子裏有文件。有一個Client表,一個Warehouse表,一個Boxes表和一個Files表。加入3個表的SQL COUNT

所以Client表有WarehouseID作爲外鍵,Boxes表有ClientID作爲外鍵,和Files表有BoxID作爲外鍵。我想統計每個客戶端在我的查詢中包含的盒子和文件的數量,以及進出倉庫的盒子數量。 BoxesFiles表上的Status字段確定框和文件是否在倉庫內或倉庫外。我跑的箱子下面的查詢和號碼是正確的:

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] 

這將產生的輸出:

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

計數的輸出是正確的。當我將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

A 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