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

问题描述 投票:0回答:4

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

表:

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):http://sqlfiddle.com/#!9/ba39ba/13

sqlFiddle(pg):http://sqlfiddle.com/#!17/bc32e/7

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

我究竟做错了什么?

mysql sql postgresql
4个回答
2
投票

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

例如

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子句中。

干杯!


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;

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

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是分开的,我可以快速检查它们,如果我对解决方案的某些部分感到满意​​,继续。

© www.soinside.com 2019 - 2024. All rights reserved.