查询联接三个表并获得一个字段的计数而不返回零值

时间:2018-12-17 15:19:54

标签: sql sql-server sql-server-2008 join count

我有三个表:Dept,DocType,Documents。我需要所有DocType及其对应的部门的列表,以及每个部门每个DocType的文档计数。每个表中都有字段可以正确链接它们。我的问题是我正确地获得了计数,但是没有任何文档的DocType没有在结果中列为零。

我想要:

Accounting    Faxes   3
Accounting    Memos   0
Accounting    Misc    10

但是我得到了:

Accounting    Faxes   3
Accounting    Misc    10

这是我的查询。有什么想法吗?

select DE.DeptName, DT.DocTypeID, COUNT(Docs.DocNumber)
from DocTypes as DT
left join Documents as Docs on Docs.DocTypeID = DT.DocTypeID
left join Dept as DE on DE.DeptID = Docs.DeptID
group by DT.DocTypeID, DE.DeptName
order by DE.DeptName, DT.DocTypeID

部门表具有: DeptID,DeptName

DocType表具有: DeptID,DocTypeID

文档表具有: DeptID,DocTypeID,DocNumber

有什么想法吗?

7 个答案:

答案 0 :(得分:0)

您可以尝试查询吗

SELECT DE.deptname, 
       DT.doctypeid, 
       Count(Docs.docnumber) 
FROM   dept AS DE 
       LEFT JOIN documents AS Docs 
              ON DE.deptid = Docs.deptid 
       LEFT JOIN doctypes AS DT 
              ON Docs.doctypeid = DT.doctypeid 
GROUP  BY DT.doctypeid, 
          DE.deptname 
ORDER  BY DE.deptname, 
          DT.doctypeid 

答案 1 :(得分:0)

切换joins。之所以没有获取doctype,是因为您使用doctype(可以为null)启动查询-因此无需“ join”。从始终存在的数据(即dept)开始查询。 试试这个:

select 
    DE.DeptName, 
    DT.DocTypeID, 
    COUNT(Docs.DocNumber)
from 
    Dept as DE
left join 
    Documents as Docs on DE.DeptID = Docs.DeptID
left join 
    DocTypes as DT on Docs.DocTypeID = DT.DocTypeID
group by 
    DT.DocTypeID, 
    DE.DeptName
order by 
    DE.DeptName, 
    DT.DocTypeID

答案 2 :(得分:0)

您没有提到正在使用哪个RDBMS,因此答案会有所不同,但是以Oracle为例,您可以使用NVL(COUNT(Docs.DocNumber),0)。基本上,如果COUNT(Docs.DocNumber)返回NULL,它将返回0。无论您使用哪种RDBMS,都会有类似的东西。

答案 3 :(得分:0)

您应该尝试以下查询:

select DE.DeptName, DT.DocTypeID, COUNT(Docs.DocNumber)
  from Dept as DE
  left join DocTypes as DT on DT.DeptID = DE.DeptID
  left join Documents as Docs on (Docs.DeptID = DE.DeptID and Docs.DocTypeID = DT.DocTypeID)
 group by DT.DocTypeID, DE.DeptName
 order by DE.DeptName, DT.DocTypeID

重要的是,如果要在结果集中将DocTypes表连接到Documents表之前。如果Documents表首先被连接,并且没有任何文档类型的条目,那么首先将没有任何连接。

除此之外,我还向您的联接中添加了Docs.DeptID = DE.DeptID,因为您只想对每个DeptId进行文档计数。 如您所指出的,建议使用所有公共列来联接表:

  

部门表具有:DeptID,DeptName

     

DocType表具有:DeptID,DocTypeID

     

文档表具有:DeptID,DocTypeID,DocNumber

没有它,您将以在问题中编写结果的方式乘以结果。无论哪种方式,计数值的总和都应该与Docs表本身中的行数完全相同-这样才可以检查是否(乘以结果)。

希望我能帮上忙!

答案 4 :(得分:0)

首先,您需要所有文档类型和所有部门的交叉产品

  

此产品之所以是叉积,是因为它为我们提供了所有可能要计数的清单。当我们从中选择时,我们将知道是否有一些我们想计数的东西不存在。在SQL中,您必须考虑集合...这给了我们要计数的东西。

因此,我们执行以下操作(我仍然不是100%哪个表具有什么数据-在这种情况下,我猜测Documents表将具有所有doc类型,Dept表将具有所有部门。)< / p>

 SELECT DocTypeID, DeptID
 FROM (SELECT DISTINCT DocTypeID FROM Documents)
 CROSS JOIN (SELECT DISTINCT DeptID FROM Dept)

然后我们将其用于分组并合并其余数据

 select DE.DeptName, docs.DocTypeID, COUNT(Docs.DocNumber)
 FORM (
   SELECT DocTypeID, DeptID
   FROM (SELECT DISTINCT DocTypeID FROM Documents)
   CROSS JOIN (SELECT DISTINCT DeptID FROM Dept)   
 ) AS base 
 left join Documents as Docs on Docs.DocTypeID = base.DocTypeID
 left join Dept as DE on DE.DeptID = base.DeptID
 group by docs.DocTypeID, DE.DeptID
 order by DE.DeptID, docs.DocTypeID

答案 5 :(得分:0)

尝试此代码,

SELECT 
    DE.DeptName, DT.DocTypeID, ISNULL(COUNT(Docs.DocNumber), 0)
FROM
    DocTypes AS DT
        LEFT JOIN
    Documents AS Docs ON Docs.DocTypeID = DT.DocTypeID
        LEFT JOIN
    Dept AS DE ON DE.DeptID = Docs.DeptID
GROUP BY DT.DocTypeID , DE.DeptName
ORDER BY DE.DeptName , DT.DocTypeID

答案 6 :(得分:0)

这是仅供参考,我们修改了要求,不再需要包含零的计数。我非常感谢您的所有建议,并保存了线程以便在时间允许的情况下继续进行工作。