2017-08-11 269 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