Table subsets comparison

时间:2015-10-30 21:38:16

标签: sql sql-server tsql sql-server-2012

I am using the AdventureWorks database and SQL Server 2012 T-SQL Recipes book and got myself into trouble on the following example :

I have to check the SalesQuota in both 2007 and 2008 from Sales.SalesPersonQuotaHistory.

SELECT sp.BusinessEntityID
, SUM(s2008.SalesQuota) AS '2008'
, SUM(S2007.SalesQuota) AS '2007'
FROM Sales.SalesPerson sp
LEFT OUTER JOIN Sales.SalesPersonQuotaHistory s2008
  ON sp.BusinessEntityID = s2008.BusinessEntityID
    AND YEAR(s2008.QuotaDate) = 2008
LEFT OUTER JOIN Sales.SalesPersonQuotaHistory s2007
  ON sp.BusinessEntityID = s2007.BusinessEntityID
    AND YEAR(s2007.QuotaDate) = 2007
GROUP BY sp.BusinessEntityID

First results are:

  BusinessEntityID 2008                  2007
---------------- --------------------- ---------------------
  274              1084000.00            1088000.00
  275              6872000.00            9432000.00
  276              8072000.00            9364000.00
  277              6644000.00            8700000.00

Just like the book says.

But then I try to get the 2008 SalesQuota with the following query:

SELECT sp.BusinessEntityID,
       SUM(spqh.SalesQuota) AS '2008'
FROM Sales.SalesPerson sp
  LEFT JOIN Sales.SalesPersonQuotaHistory spqh
   ON sp.BusinessEntityID = spqh.BusinessEntityID
     AND YEAR(spqh.QuotaDate) = 2008 
GROUP BY sp.BusinessEntityID

and got this:

 BusinessEntityID 2008
---------------- ---------------------
 274              271000.00
 275              1718000.00
 276              2018000.00
 277              1661000.00

What am I doing wrong here? I think I miss something on those LEFT JOINs but I can't figure out what.

This one gives the same result:

SELECT BusinessEntityID
, SUM(SalesQuota) AS '2008'
FROM Sales.SalesPersonQuotaHistory
WHERE YEAR(QuotaDate) = 2008 
GROUP BY BusinessEntityID


 BusinessEntityID 2008
 ---------------- ---------------------
 274              271000.00
 275              1718000.00
 276              2018000.00

3 个答案:

答案 0 :(得分:1)

I don't think you first example is correct.

SELECT sp.BusinessEntityID, 
       SUM(CASE WHEN YEAR(s.QuotaDate) = 2007 THEN s.SalesQuota ELSE 0 END) AS '2007',
       SUM(CASE WHEN YEAR(s.QuotaDate) = 2008 THEN s.SalesQuota ELSE 0 END) AS '2008'
FROM Sales.SalesPerson sp
LEFT JOIN Sales.SalesPersonQuotaHistory s ON sp.BusinessEntityID = s.BusinessEntityID
GROUP BY sp.BusinessEntityID

答案 1 :(得分:1)

Your first query is probably creating a cartesian product of the results. Instead, I would use conditional aggregation to get both values (which should match your second query):

SELECT sp.BusinessEntityID,
   SUM(CASE WHEN Year(spqh.QuotaDate) = 2007 then spqh.SalesQuota end) AS '2007',
   SUM(CASE WHEN Year(spqh.QuotaDate) = 2008 then spqh.SalesQuota end) AS '2008'
FROM Sales.SalesPerson sp
  LEFT JOIN Sales.SalesPersonQuotaHistory spqh
      ON sp.BusinessEntityID = spqh.BusinessEntityID
GROUP BY sp.BusinessEntityID

答案 2 :(得分:1)

If you aren't returning any columns from the Sales.SalesPerson table, you can exclude it and use pivot to get your desired results: select BusinessEntityID, [2008], [2007] from ( select BusinessEntityID, year(QuotaDate) as SalesQuotaYear, sum(SalesQuota) as SalesQuota from Sales.SalesPersonQuotaHistory where year(QuotaDate) in(2007,2008) group by BusinessEntityID, year(QuotaDate) ) as t pivot ( sum(SalesQuota) for SalesQuotaYear in([2007],[2008]) ) as p