简体   繁体   English

具有非唯一日期的SQL Sum

[英]SQL Sum with non unique date

I'm trying to write a SQL query that will sum total production from the following two example tables: 我正在尝试编写一个SQL查询,该查询将汇总以下两个示例表中的总产量:

Table: CaseLots
DateProduced        kgProduced
October 1, 2013     10000
October 1, 2013     10000
October 2, 2013     10000

Table: Budget
OperatingDate       BudgetHours
October 1, 2013     24
October 2, 2013     24

I would like to output a table as follows: 我想输出如下表:

TotalProduction   TotalBudgetHours    
30000                   48

Here is what I have for code so far: 到目前为止,这是我所拥有的代码:

SELECT 
Sum(kgProduced) AS TotalProduction, Sum(BudgetHours) AS TotalBudgetHours
FROM 
dbo.CaseLots INNER JOIN dbo.Budget ON dbo.CaseLots.DateProduced = dbo.Budget.OperatingDate
WHERE 
dbo.Budget.OperatingDate BETWEEN '2013-10-01' AND '2013-10-02'

It seems that the query is double summing the budget hour in instances where more than one case lot is produced in a day. 在一天中产生多个案件的情况下,查询似乎是预算小时的两倍。 The table I'm getting is as follows: 我得到的表如下:

Total Production     BudgetHours
30000                72

How do I fix this? 我该如何解决?

Think about what the INNER JOIN is doing. 想想INNER JOIN在做什么。

For every row in CaseLot, its finding any row in Budget that has a matching date. 对于CaseLot中的每一行,它会在Budget中找到具有匹配日期的任何行。

If you were to remove your aggregation statements in SQL, and just show the inner join, you would see the following result set: 如果要删除SQL中的聚合语句,而仅显示内部联接,则会看到以下结果集:

DateProduced kgProduced OperatingDate BudgetHours 日期生产的公斤生产的经营日期预算小时

October 1, 2013 10000 October 1, 2013 24 2013年10月1日10000 2013年10月1日24

October 1, 2013 10000 October 1, 2013 24 2013年10月1日10000 2013年10月1日24

October 2, 2013 10000 October 2, 2013 24 2013年10月2日10000 2013年10月2日24

(dammit StackOverflow, why don't you have Markdown for tables :( ) (该死的StackOverflow,为什么你没有Markdown的表:()

Running your aggregation on top of that it is easy to see how you get the 72 hours in your result. 在此基础上运行聚合很容易看到您如何获得72小时的结果。

The correct query needs to aggregate the CaseLots table first, then join onto the Budget table. 正确的查询需要首先聚合CaseLots表,然后再联接到Budget表。

SELECT DateProduced, TotalKgProduced, SUM(BudgetHours) AS TotalBudgetHours
FROM
(
    SELECT DateProduced, SUM(kgProduced) AS TotalKgProduced
    FROM CaseLots
    GROUP BY DateProduced
) AS TotalKgProducedByDay
INNER JOIN
Budget
ON TotalKgProducedByDay.DateProduced = Budget.OperatingDate
WHERE DateProduced BETWEEN '1 Oct 2013' AND '2 Oct 2013'
GROUP BY DateProduced

The problem is in the INNER JOIN produces a 3 row table since the keys match on all. 问题在于INNER JOIN产生3行表,因为所有键都匹配。 So there is three '24's with a sum of 72. 因此,存在三个“ 24”,总和为72。

To fix this, it would probably be easier to split this into two queries. 要解决此问题,将其分为两个查询可能会更容易。

SELECT Sum(kgProduced) AS TotalProduction
FROM dbo.CaseLots
WHERE dbo.CaseLots.OperatingDate BETWEEN '2013-10-01' AND '2013-10-02'

LEFT JOIN

SELECT Sum(BudgetHours) AS TotalBudgetHours
FROM dbo.Budget
WHERE dbo.Budget.OperatingDate BETWEEN '2013-10-01' AND '2013-10-02'

This could be easily achieved by this: 这可以通过以下方式轻松实现:

SELECT
   (SELECT SUM(kgProduced) FROM dbo.CaseLots WHERE DateProduced BETWEEN '2013-10-01' AND '2013-10-02') AS TotalProduction,
   (SELECT SUM(BudgetHours) FROM dbo.Budget WHERE OperatingDate BETWEEN '2013-10-01' AND '2013-10-02') AS TotalBudgetHours

There's no need for joining the two tables. 无需加入两个表。

Try this: 尝试这个:

select DateProduced,TotalProduction,TotalBudgetHours from
  (select DateProduced,sum(kgProduced) as TotalProduction 
  from CaseLots group by DateProduced) p
  join
  (select OperatingDate,sum(BudgetHours) as TotalBudgetHours 
  from Budget group by OperatingDate) b
  on (p.DateProduced=b.OperatingDate)
where p.DateProduced between '2013-10-01' AND '2013-10-02'

The other answers are simpler for this particular case. 对于这种特殊情况,其他答案更为简单。 However if you needed to SUM 10 different values on the CaseLots table, you'd need 10 different subqueries. 但是,如果你需要SUM在10个不同的值CaseLots表,你需要10个不同的子查询。 The following is a general, more scaleable solution: 以下是一个通用的,可扩展的解决方案:

SELECT 
    SUM(DayKgProduced) AS TotalProduction, 
    SUM(BudgetHours) AS TotalBudgetHours
FROM (
    SELECT 
        DateProduced,
        SUM(kgProduced) AS DayKgProduced, 
    FROM dbo.CaseLots 
    WHERE DateProduced BETWEEN '2013-10-01' AND '2013-10-02' 
    GROUP BY DateProduced
) DailyTotals
INNER JOIN dbo.Budget b ON DailyTotals.DateProduced = b.OperatingDate

First you SUM the production of each CaseLot without having to SUM the BudgetHours. 首先,你SUM生产的每一个CaseLot不必SUM的BudgetHours。 If you used a SELECT * FROM in the query above you'd see: 如果在上面的查询中使用SELECT * FROM ,则会看到:

Date        DayKgProduced  BudgetHours
2013-10-01  20000          24 
2013-10-02  10000          24

But you want the overall total, so we SUM those daily values, correctly producing: 但是,您需要总计,因此我们将这些每日值SUM ,正确得出:

TotalProduction  TotalBudgetHours
30000            48 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM