如何显示sum函数中的结果集为零

时间:2011-08-26 15:58:05

标签: sql sql-server sql-server-2008 sum

我使用函数sum来为客户添加所有发票:      SUM(distinct(T1。[GTotal]))为InvoiceTotal

我知道我有一些客户有发票但发票总数为0。 该功能不会显示这些记录。

如何确保查询显示它们?


SELECT DISTINCT
    T2.CardCode as CustomerId, 
    T2.CntctPrsn as ContactPerson, 
    T2.Phone1 as Phone, 
    T4.GroupName as CustomerType, 
    T5.descript as Territory,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.Address ELSE NULL END) AS BillToCustomerName,  
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.Street ELSE NULL END) AS BillToAddress1,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.Block ELSE NULL END) AS BillToAddress2,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.City ELSE NULL END) AS BillToCity,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.State ELSE NULL END) AS BillToState,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.ZipCode ELSE NULL END) AS BillToZipCode,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.County ELSE NULL END) AS BillToCounty,
    MAX(CASE WHEN T3.AdresType = 'B' THEN T3.Country ELSE NULL END) AS BillToCountry,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.Address ELSE NULL END) AS ShipToCustomerName,  
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.Street ELSE NULL END) AS ShipToAddress1,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.Block ELSE NULL END) AS ShipToAddress2,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.City ELSE NULL END) AS ShipToCity,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.State ELSE NULL END) AS ShipToState,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.ZipCode ELSE NULL END) AS ShipToZipCode,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.County ELSE NULL END) AS ShipToCounty,
    MAX(CASE WHEN T3.AdresType = 'S' THEN T3.Country ELSE NULL END) AS ShipToCountry,
    COUNT(distinct(T0.[DocNum])) as Invoices,
    SUM(distinct(T1.[GTotal])) as InvoiceTotal 
FROM asap.dbo.OINV T0  
    INNER JOIN asap.dbo.INV1 T1 ON T0.DocEntry = T1.DocEntry 
    INNER JOIN asap.dbo.OCRD T2 ON T0.CardCode = T2.CardCode 
    INNER JOIN asap.dbo.CRD1 T3 ON T2.CardCode = T3.CardCode
    INNER JOIN asap.dbo.OCRG T4 ON T2.GroupCode = T4.GroupCode 
    INNER JOIN asap.dbo.OTER T5 ON T2.Territory = T5.territryID 
WHERE T0.DocDate >= '2008-01-01 00:00:00.000' AND 
      T0.DocDate <= '2011-12-31 00:00:00.000' AND 
      T4.[GroupName] ='WholeSale' AND   
      T5.[descript] = 'Region 04' 
GROUP BY T2.[CardCode], 
      T2.[CntctPrsn], 
      T2.[Phone1], 
      T4.[GroupName], 
      T5.[descript]

我收到所有发票总额,但是如果有发票没有任何$,则他们没有在结果中显示。该报告将用于查看特定区域的现有客户群,并允许销售人员定位长时间未购买或销售额较低的客户。出于保密原因,这里是结果的简要版本:

Customer  Customer Type  Territory  Total Invoices  Total $ Spent
--------  -------------  ---------  --------------  -------------
C100177   Wholesale      Region 04  77              15813.1
C100208   Wholesale      Region 04  2               540
C100209   Wholesale      Region 04  5               809
C100213   Wholesale      Region 04  2               344.7
C100215   Wholesale      Region 04  5               1249.8

以下是缺失的记录:

Customer  Customer Type  Territory  Total Invoices  Total $ Spent
--------  -------------  ---------  --------------  -------------
C110885   Wholesale      Region 04  1               0
C123218   Wholesale      Region 04  1               0
C128694   Wholesale      Region 04  1               0
C158528   Wholesale      Region 04  1               0
C168646   Wholesale      Region 04  1               0

3 个答案:

答案 0 :(得分:2)

听起来有些客户的发票表中没有任何行?您应该使用外部联接。

SELECT
  c.CustomerId
 ,c.CustomerName
 ,SUM(COALESCE(i.GTotal, 0)) AS InvoiceTotal
FROM Customers c
  LEFT OUTER JOIN Invoices i ON c.CustomerId = i.CustomerId
GROUP BY c.CustomerId, c.CustomerName
ORDER BY c.CustomerName

答案 1 :(得分:0)

首先运行此查询

select count(*)
FROM asap.dbo.OINV T0       

然后单独添加下面的每个连接条件并再次运行查询

INNER JOIN asap.dbo.INV1 T1 ON T0.DocEntry = T1.DocEntry      
INNER JOIN asap.dbo.OCRD T2 ON T0.CardCode = T2.CardCode      
INNER JOIN asap.dbo.CRD1 T3 ON T2.CardCode = T3.CardCode     
INNER JOIN asap.dbo.OCRG T4 ON T2.GroupCode = T4.GroupCode      
INNER JOIN asap.dbo.OTER T5 ON T2.Territory = T5.territryID  

其中一个连接条件会降低计数。例如,如果没有金额的发票的T0.DocEntry为空,那么第一个JOIN将降低您的计数......

一旦知道导致问题的表,就应该更容易修复

答案 2 :(得分:0)

我同意Rob Boek的观点,即你的解决方案应该在某处使用至少一个外连接。在我看来,要加入外部的表是OINVOCRD,但是您还应该将一些条件从WHERE移动到相应的ON子句,用于外连接采取必要的效果。

更具体地说,我可能会重新安排这样的连接和条件:

…
FROM asap.dbo.OCRD T2  
    LEFT JOIN asap.dbo.OINV T0 ON T0.CardCode = T2.CardCode AND 
        T0.DocDate >= '2008-01-01 00:00:00.000' AND 
        T0.DocDate <= '2011-12-31 00:00:00.000' 
    LEFT JOIN asap.dbo.INV1 T1 ON T0.DocEntry = T1.DocEntry 
    INNER JOIN asap.dbo.CRD1 T3 ON T2.CardCode = T3.CardCode
    INNER JOIN asap.dbo.OCRG T4 ON T2.GroupCode = T4.GroupCode 
    INNER JOIN asap.dbo.OTER T5 ON T2.Territory = T5.TerritoryID 
WHERE T4.[GroupName] ='WholeSale' AND   
      T5.[descript] = 'Region 04' 
…

我做的一件事同意Rob是如何应用COALESCE来消除SUM的可能的NULL结果。在我看来,COALESCE应该应用于SUM结果,而不是其参数。