如何在连接表中SUM值而不会在第一个表中搞砸总值?

时间:2014-10-22 13:27:53

标签: mysql sql inner-join

我想SELECT计算客户数量,客户订单总数和特定州的客户数量。

我知道如何轻松地在两个查询中执行此操作,但是将使用相同的WHERE约束,因此在一个查询中执行此操作并避免重复似乎更好。我渴望改进我的SQL,但我无法弄清楚如何组合它们。将它们作为两个单独的查询感觉非常笨拙。

有没有办法将它们结合起来?我应该考虑哪些因素来确定将它们组合是一个好主意?


Customers

*-------------*-------------*--------------*------------*
| ID_Customer | ID_State    | Name         |  ...etc... |
*-------------*-------------*--------------*------------*

States

*-------------*-------------*
| ID_State    | Name        |
*-------------*-------------*

Orders

*----------*-------------*--------------*------------*
| ID_Order | ID_Customer |   ...etc...  | Total      |
*----------*-------------*--------------*------------*

查询1.1 - 选择客户数和特定州的客户数

SELECT 
COUNT(*) AS Customers, 
SUM(States.Name = 'California') AS California_Customers, 
SUM(States.Name = 'New York') AS NewYork_Customers 

FROM Customers 
INNER JOIN States ON Customers.ID_State = States.ID_State 

查询1.2 - 选择客户订单总计总和

SELECT 
SUM(Total) AS SumOfOrderTotals

FROM Orders 
INNER JOIN Customers ON Customers.ID_Customer = Orders.ID_Customer 

查询2 - 尝试将查询合并为一个(不起作用)

SELECT 
COUNT (DISTINCT(Customers.ID_Customer)) AS Customers, 
SUM (Orders.Total) AS SumOfOrderTotals, 
SUM (States.Name = 'California') AS California_Customers, 
SUM (States.Name = 'New York') AS NewYork_Customers 

FROM 
Customers 
INNER JOIN Orders ON Customers.ID_Customer = Orders.ID_Customer 
INNER JOIN States ON Customers.ID_State = States.ID_State 

显然这不起作用,因为INNER JOINCustomers之间的Orders表示States.Name被计为x N (其中 N 是每个客户的订单数量),使这些总数错误。


我考虑过Subquery,但是我不确定如何在这种情况下应用一个(如果那是我应该做的)。

2 个答案:

答案 0 :(得分:1)

您需要在join之前进行聚合或使用子查询:

SELECT COUNT(DISTINCT(c.ID_Customer)) AS Customers, 
       o.SumOfOrderTotals, 
       SUM(s.Name = 'California') AS California_Customers, 
       SUM(s.Name = 'New York') AS NewYork_Customers 
FROM Customers c JOIN
     States s
     ON c.ID_State = s.ID_State CROSS JOIN
     (SELECT SUM(Total) as SumOfOrderTotals
      FROM Orders o
     ) o;

您也可以将其写为:

SELECT COUNT(DISTINCT(c.ID_Customer)) AS Customers, 
       (SELECT SUM(Total)
        FROM Orders o
       ) as SumOfOrderTotals, 
       SUM(s.Name = 'California') AS California_Customers, 
       SUM(s.Name = 'New York') AS NewYork_Customers 
FROM Customers c JOIN
     States s
     ON c.ID_State = s.ID_State;

答案 1 :(得分:1)

将子查询放在放置任何其他字段的位置,作为SELECT子句中的另一个字段。

SELECT 
  COUNT(*) AS Customers, 
  SUM(States.Name = 'California') AS California_Customers, 
  SUM(States.Name = 'New York') AS NewYork_Customers,
  (SELECT SUM(Total) FROM Orders) AS SumOfOrderTotals
FROM Customers 
INNER JOIN States ON Customers.ID_State = States.ID_State;