SQL Server COUNT多个表返回错误结果

SQL Server COUNT多个表返回错误结果,sql,sql-server,Sql,Sql Server,以下是表格: 来自acc账户 AccountName ------------- Account #1 Account #3 Account #2 来自部门,作为与客户合并的部门 AccountName DivisionName ----------- --------------------------- Account #1 Division TWO for Account #1 Account #1 Division ONE for Account #1 来自AccountSupp

以下是表格:

来自acc账户

AccountName
-------------
Account #1
Account #3
Account #2
来自部门,作为与客户合并的部门

AccountName DivisionName
----------- ---------------------------
Account #1  Division TWO for Account #1
Account #1  Division ONE for Account #1
来自AccountSuppliers作为acc_sup(多对多加入)

以下是查询:

SELECT 
    acc.AccountName,
    COUNT(div.AccountId) AS CountDivisions,
    COUNT(acc_sup.AccountId) AS CountSuppliers 
FROM 
    Account AS acc
LEFT JOIN 
    Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN 
    AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY 
    acc.AccountName
结果如下:

AccountName CountDivisions  CountSuppliers
----------- --------------- --------------
Account #1  6               6
Account #2  0               2
Account #3  0               0
应该是:

AccountName CountDivisions  CountSuppliers
----------- --------------- --------------
Account #1  2               3
Account #2  0               2
Account #3  0               0
请注意,添加DISTINCT关键字也会产生奇怪的结果:

SELECT 
    acc.AccountName,
    COUNT(DISTINCT div.AccountId) AS CountDivisions,
    COUNT(DISTINCT acc_sup.AccountId) AS CountSuppliers 
FROM 
    Account AS acc
LEFT JOIN 
    Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN 
    AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY 
    acc.AccountName
产生:

AccountName CountDivisions  CountSuppliers
----------- --------------- --------------
Account #1  1               1
Account #2  0               1
Account #3  0               0
嗯?我可能忽略了一些简单的东西,但这个结果显然是不正确的。有人能为我推荐一种正确的方法来编写这个查询以获得正确的结果吗


谢谢

只需在要计算唯一值的位置添加
DISTINCT

SELECT acc.AccountName,
COUNT(DISTINCT div.AccountId) AS CountDivisions,
COUNT(DISTINCT acc_sup.AccountId) AS CountSuppliers 
FROM Account AS acc
LEFT JOIN Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY acc.AccountName, div.AccountId, acc_sup.AccountId

您可以在count statemetns中使用distinct关键字

SELECT acc.AccountName,
COUNT(distinct div.AccountId) AS CountDivisions,
COUNT(distinct acc_sup.AccountId) AS CountSuppliers 
FROM Account AS acc
LEFT JOIN Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY acc.AccountName
或更节省资源的方式:

 SELECT 
   acc.AccountName,
   (SELECT COUNT(*) FROM Division where div.AccountId = acc.Id) CountDivisions,
   (SELECT COUNT(*) FROM AccountSupplier WHERE acc_sup.AccountId = acc.Id) AS CountSuppliers 
 FROM aCCOUNT AS acc

查询中导致错误结果的问题是您要求计算错误的字段

SELECT 
    acc.AccountName,
    COUNT(div.AccountId) AS CountDivisions,
    COUNT(acc_sup.AccountId) AS CountSuppliers 
FROM 
    Account AS acc
LEFT JOIN 
    Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN 
    AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY 
    acc.AccountName
当count更改为CountDivisions时,-
div.AccountId
是联接中使用的字段,因此组中的每一行的值都是相同的-计算这些不同的值时,无论有多少个匹配的值,当然都是1

计数应该在子表中的唯一字段上,假设您有一个
ID
字段,则其如下所示:

SELECT 
    acc.AccountName,
    COUNT(DISTINCT div.Id) AS CountDivisions,
    COUNT(DISTINCT acc_sup.Id) AS CountSuppliers 
FROM 
    Account AS acc
LEFT JOIN 
    Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN 
    AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY 
    acc.AccountName

你很接近。您只是错过了计算聚合所需的列

根据您的设置数据,让我们看一下将要处理的给定查询中的数据。我们希望使用
左外部联接
s,因为我们希望计算所有
帐户名
s,即使没有任何
部门名
s或
供应商名
s。对于那些,我们将得到
null
,这将转换为
0
计数

因此:

给了我们:

这为我们提供了我们所期望的计数:

AccountName | CountDivisions | CountSuppliers :---------- | -------------: | -------------: 会计科目1 | 2 | 3 Acct2 | 0 | 2 Acct3 | 0 | 0
dbfiddle

提示:
DISTINCT
inside
COUNT()
会有帮助。@yogesharma-否。我尝试将DISTINCT添加到计数聚合中。我得到一个不同的结果集,但它也是错误的。请添加您的数据。Simonare--您的第一个建议也会产生一个奇怪的结果集。我按问题编辑以显示这一点。然而,你的第二个建议非常有效。这是首选的解决方案。谢谢@CCPony:这个答案也显示了问题所在,
COUNT(distinct div.AccountId)
vs
div.AccountId=acc.Id
在子查询的where子句中-您计算的是帐户Id,而不是唯一标识行的标识值-这就是为什么添加distinct关键字会产生值1的原因,我没有按提交按钮。根据您使用的数据和索引(以及您的SQL Server版本),基于纯
JOIN
with
DISTINCT
或使用Simonare的相关子查询示例,您可能会获得不同的性能。你会想测试的。
SELECT 
    acc.AccountName,
    COUNT(DISTINCT div.Id) AS CountDivisions,
    COUNT(DISTINCT acc_sup.Id) AS CountSuppliers 
FROM 
    Account AS acc
LEFT JOIN 
    Division AS div ON (div.AccountId = acc.Id)
LEFT JOIN 
    AccountSupplier AS acc_sup ON (acc_sup.AccountId = acc.Id)
GROUP BY 
    acc.AccountName
SELECT *
FROM Account acc
LEFT JOIN Division div ON (div.AccountId = acc.Id)
LEFT JOIN AccountSupplier acc_sup ON (acc_sup.AccountId = acc.Id)  ;
id | AccountName | accountID | DivisionName | accountID | SupplierName -: | :---------- | --------: | :----------- | --------: | :----------- 1 | Acct1 | 1 | Div2 | 1 | Supplier6 1 | Acct1 | 1 | Div2 | 1 | Supplier1 1 | Acct1 | 1 | Div2 | 1 | Supplier3 1 | Acct1 | 1 | Div1 | 1 | Supplier6 1 | Acct1 | 1 | Div1 | 1 | Supplier1 1 | Acct1 | 1 | Div1 | 1 | Supplier3 2 | Acct2 | null | null | 2 | Supplier1 2 | Acct2 | null | null | 2 | Supplier2 3 | Acct3 | null | null | null | null
SELECT 
    acc.AccountName,
    COUNT(DISTINCT div.DivisionName) AS CountDivisions,
    COUNT(DISTINCT acc_sup.SupplierName) AS CountSuppliers 
FROM Account acc
LEFT JOIN Division div ON div.AccountId = acc.Id
LEFT JOIN AccountSupplier acc_sup ON acc_sup.AccountId = acc.Id
GROUP BY acc.AccountName ;
AccountName | CountDivisions | CountSuppliers :---------- | -------------: | -------------: Acct1 | 2 | 3 Acct2 | 0 | 2 Acct3 | 0 | 0