内连接三个表导致相乘的值

时间:2018-02-27 11:11:30

标签: mysql sql postgresql

我正试图(比方说)收集客户报告。 在该报告中,我想要包括每个客户的订单总数和票号。

表:

Customer(id, name)
Order(id, customer_id, amount)
support_ticket(id, customer_id)

查询:

select 
  c.id as 'Customer', 
  count(distinct t.id) as "Ticket count", 
  count(distinct o.id) as "Order count", 
  sum(o.amount) as 'Order Amount' 

from customer as c
  inner join `order` as o on c.id = o.customer_id
  inner join support_ticket as t on c.id = t.customer_id

group by c.id

由于我在两个表上加入了customer.id,因此我得到了所有可能的组合,因为我得到了所有可能的组合,所以如果客户端是多个票证,sum(o.amount)我们会成倍增加“重复的行”

sqlFiddle(mysql):select 2

sqlFiddle(pg):http://sqlfiddle.com/#!9/ba39ba/13

这似乎是一个简单的案例,但我一直在考虑这个问题,我认为找不到报告的正确方法。

我做错了什么?

4 个答案:

答案 0 :(得分:2)

您最好的选择是将订单表中的聚合重写为派生表;

EG

select 
  c.id as 'Customer', 
  count(distinct t.id) as "Ticket count", 
  o.amount as 'Order Amount' ,
  o.[Order count]
from customer as c
  inner join 
  (SELECT 
    o.customer_id, 
    sum(amount) as amount , 
    count(distinct o.id) as "Order count" 
    from [order] 
    group by o.customer_id)
   as o on c.id = o.customer_id
  inner join support_ticket as t on c.id = t.customer_id

group by 
  c.id , 
  o.amount ,
  o.[Order count]

请注意,派生表列会添加到底部的group by子句中。

干杯!

答案 1 :(得分:2)

只需计算子查询中的order值并加入即可。

SELECT
  c.id as 'Customer'
  ,count(DISTINCT st.id) as 'Ticket Count'
  ,o.`Order Count`
  ,o.amount as `Order Amount`
FROM customer c
INNER JOIN support_ticket st
  on c.id = st.customer_id
INNER JOIN (
  SELECT 
    customer_id
    ,SUM(amount) as 'amount'
    ,count(distinct id) as 'Order Count'
  FROM `order`
  group by customer_id
) o
  on c.id = o.customer_id
GROUP BY c.id;

答案 2 :(得分:1)

select c.id as 'Customer'
      ,t2.count_ticket as "Ticket count"
      ,t1.count_order as "Order count"
      ,t1.amount as 'Order Amount' 
from customer as c
inner join (select customer_id
                  ,count(id) as count_order
                  ,sum(amount) as amount 
            from Order group by customer_id) t1  
on c.id = t1.customer_id
inner join (select customer_id
                  ,count(id) as count_ticket 
            from support_ticket group by customer_id) t2
on c.id = t2.customer_id

答案 3 :(得分:0)

在像你这样的情况下,当我认为我的问题的解决方案应该相当简单但我无法绕过它时,我倾向于使用WITH子句。

不是因为它更好,而是因为它通过分解复杂性帮助我更好地理解我的代码。首先,我创建一个相对简单的临时。解决我问题的第一部分。

WITH temp AS (
 SELECT
    c.id AS "customer",
    COUNT(DISTINCT o.id) AS "order_count",
    SUM(o.amount) AS "order_amount"
 FROM customer AS c
 INNER JOIN  "order" AS o on c.id = o.customer_id
 GROUP BY c.id
)

然后我只是从temp中选择我的解决方案的前半部分,以这种方式添加所有中间结果,并解决我的初始sql的第二部分。

SELECT
    temp.customer,
    COUNT(DISTINCT t.id) as "ticket_count",
    temp.order_count,
    temp.order_amount
FROM temp
INNER JOIN support_ticket as t on temp.customer = t.customer_id
GROUP BY temp.customer, temp.order_count, temp.order_amount

原则与之前的所有答案相同,但SELECTS是分开的,我可以快速检查它们,如果我对解决方案的某些部分感到满意​​,请继续。