为什么这些总和操作不应该“加起来”呢?

时间:2017-03-28 20:07:27

标签: sql sql-server tsql

注意:这是关注[on,up]到this question以及this questionenter image description here

这些回复都让我前进,但即使是最后一回事,虽然它改善了问题但并没有完全解决这个问题。

此查询:

select monthlysales, MemberNo from ReportingMonthlySales
where unit = 'Abuelos' and CYear = 2017 and cmonth = 3

...返回一堆行,其中每月销售总额为$ 364,121.69

但是,当我尝试将这些月度销售分成四个类别时,虽然它们的总和应该是相同的,但总和实际上是天文数字“更大” - 下面的代码返回了大大膨胀的值23,924,211.30

2400万美元几乎是实际总数364,000美元的70倍。为什么会出现这种“疯狂”的通货膨胀?

这是花哨的裤子,但显然是竹编码:

declare @Unit varchar(30);
declare @Year int = 2017;
declare @Month int = 3;
declare @paramdate datetime;
set @paramdate = convert(datetime,convert(char(4),@Year)
                +right('0'+convert(varchar(2),@month),2)
                +'01') 

IF OBJECT_ID('tempdb.dbo.#Units', 'U') IS NOT NULL
DROP TABLE #Units

select distinct unit
into #Units
from ReportingMonthlySales;

select 
    u.Unit
  , New      = sum(case when ccl.Subcategory = 'New'      then rms.MonthlySales else 0 end)
  , Assumed  = sum(case when ccl.Subcategory = 'Assumed'  then rms.MonthlySales else 0 end)
  , Existing = sum(case when ccl.Subcategory = 'Existing' then rms.MonthlySales else 0 end)
  , Organic  = sum(case when ccl.Subcategory = 'Organic'  then rms.MonthlySales else 0 end)
from #Units u
  left join CustomerCategoryLog ccl 
    on u.Unit = ccl.Unit
   and @paramdate >= ccl.begindate and
   (@paramdate <= ccl.enddate OR ccl.enddate is null)
  left join ReportingMonthlySales rms
    on u.Unit = rms.Unit
   and rms.cyear  = @year
   and rms.cmonth = @month
group by u.unit;

The two tables queried are:

CustomerCategoryLog
-------------------
MemberNo (VarChar)
Unit (VarChar)
Custno (VarChar)
Category (VarChar)
Subcategory (VarChar)
BeginDate (DateTime)
EndDate (DateTime)
ChangedBy (VarChar)
ChangedOn (DateTime)

ReportingMonthlySales
---------------------
AutoID (Int)
Unit (VarChar)
MemberNo (VarChar)
NumUnits (Int)
MonthlySales (Money)
CYear (Int)
Cmonth (Int)
CreateDate (DateTime)

fancy-pants sql中有什么问题,或者......?!?

4 个答案:

答案 0 :(得分:1)

我怀疑左连接和Or ccl.enddate is null生成了1到多个

也许直接的内部联合将纠正通货膨胀

select 
    u.Unit
  , New      = sum(case when ccl.Subcategory = 'New'      then rms.MonthlySales else 0 end)
  , Assumed  = sum(case when ccl.Subcategory = 'Assumed'  then rms.MonthlySales else 0 end)
  , Existing = sum(case when ccl.Subcategory = 'Existing' then rms.MonthlySales else 0 end)
  , Organic  = sum(case when ccl.Subcategory = 'Organic'  then rms.MonthlySales else 0 end)
from #Units u
join CustomerCategoryLog   ccl on u.Unit = ccl.Unit and @paramdate >= ccl.begindate and @paramdate <= ccl.enddate
join ReportingMonthlySales rms on u.Unit = rms.Unit and rms.cyear  = @year and rms.cmonth = @month
group by u.unit;

答案 1 :(得分:1)

您正在RMS表和这些其他表之间进行连接。您的代码假定它将为RMS表中的每条记录找到一条记录。这不是真的。这是报告和汇总多行的原因。我认为最有可能的是,对于特定的单位和@paramdate,有多个CCL条目。

答案 2 :(得分:1)

我认为这会造成重复

select distinct unit
into #Units
from ReportingMonthlySales;

你基本上从表中插入了相同的数据并在左边的连接中使用..

尝试更新后的脚本

  SELECT
  rms.Unit,
  New = SUM(CASE
    WHEN ccl.Subcategory = 'New' THEN rms.MonthlySales
    ELSE 0
  END),
  Assumed = SUM(CASE
    WHEN ccl.Subcategory = 'Assumed' THEN rms.MonthlySales
    ELSE 0
  END),
  Existing = SUM(CASE
    WHEN ccl.Subcategory = 'Existing' THEN rms.MonthlySales
    ELSE 0
  END),
  Organic = SUM(CASE
    WHEN ccl.Subcategory = 'Organic' THEN rms.MonthlySales
    ELSE 0
  END)
FROM ReportingMonthlySales rms
inner JOIN CustomerCategoryLog ccl
  ON rms.Unit = ccl.Unit
where
  AND @paramdate >= ccl.begindate
  AND (@paramdate <= isnull(ccl.enddate,getdate())
  )
 AND
   rms.cyear = @year
  AND rms.cmonth = @month
GROUP BY rms.unit;

答案 3 :(得分:0)

您的CustomerCategoryTable就其名称所暗示的可能为同一UnitNo的不同CustNo有多条记录,这使得您的第一个左连接返回重复行,这将使月销售额倍增,我认为没有解决方案查询,除非您尝试修复架构本身的一个简单信息,您试图找到每个单元的月销售额,因为它的子类别不同,而您的ReportingMonthlySales表没有关于子类别的任何信息。