[英]SQL COUNT on 3 tables with JOIN
我在數據庫中有 4 個表。 倉庫包含客戶擁有的箱子,箱子里有文件。 有一個Client
表、一個Warehouse
表、一個Boxes
表和一個Files
表。
所以Client
表有WarehouseID
作為外鍵, Boxes
表有ClientID
作為外鍵, Files
表有BoxID
作為外鍵。 我想統計每個客戶在我的查詢中擁有的箱子和文件的數量,以及進出倉庫的箱子數量。 Boxes
和Files
表上的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
,額外的行會增加計數。 由於倉庫只有一行,因此該連接不會影響計數。 如何修改我的查詢以獲得正確數量的進出倉庫的文件和箱子?
一個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
正如 Andomar 所提到的,除了 Count(*) 之外,我還包括了“as myColumnOne”和“myColumnTwo”,因為它在 SQL Server 2018 上是必需的:
select *
from table1 t1
join (
select table1_id
, count(*) as myColumnOne
from table2
group by
table1_id
) t2
on t2.table1_id = t1.id
join (
select table1_id
, count(*) as myColumnTwo
from table3
group by
table1_id
) t3
on t3.table1_id = t1.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.