2

我已经尝试了很多组合,所以也许我只是做错了。好吧,我肯定做错了。

我知道代码总是在 Stack Overflow 上被请求,但它会混淆这个问题,因为我的代码现在已经变异成另一种语言。

困惑:

有两个WHERE子句,无论我把它放在哪里,我要么得到一个错误,要么JOIN不起作用

问题:

我有 4 张桌子:

customers- 即使没有付款,我也需要返回所有行,但前提是customer_status = 1

payments- 包含customer_id链接到customers表 - 我需要从返回的 SUMpayment_amount仅当payment_status = 1

branches- 包含customer_id链接到customers

managers- 包含branch_id链接到branches

CUSTOMER    |    TOTAL_RECEIVED    |    BRANCH      |    MANAGER_NAME
----------------------------------------------------------------------
Pepsi       |    £1000             |    London      |    Mr Smith
Coca Cola   |                      |    Manchester  |    Mr Beckham
Dr Pepper   |    £2500             |    Shanghai    |    Mr Miagi
Duff        |                      |    Springfield |    Mr Simpson

如您所见,coca cola 和 duff 尚未付款(付款表中没有记录)但它仍应列出

  • 所以客户都应该出现如果customer_status = 1
  • SUM仅当它在数据库中并且 payment_status = 1 时才支付
  • Branch 和 Manager 应该列出该客户,因为它始终在数据库中
  • 经理在自己的桌子上,因为有很多并且在不同的时间分配到不同的分支机构(我感觉有人可能会问)

选择的字段和摘要

c.customer_id, c.customer_companyname, c.customer_status FROM customers c WHERE c.customer_status = 1

SUM(p.payment_amount) as total_received, p.customer_id, p.payment_status FROM payments p WHERE p.payment_status = 1

b.branch_id, b.branch, b.customer_id FROM branches b WHERE b.customer_id = c.customer_id

m.manager_id, m.manager_name, m.branch_id FROM managers m WHERE m.branch_id = b.branch_id
4

2 回答 2

3

解决这个问题的关键是将支付条件放入连接条件

SELECT 
    c.customer_id,
    c.customer_companyname,
    c.customer_status,
    SUM(p.payment_amount) as total_received,
    b.branch_id,
    b.branch,
    m.manager_id,
    m.manager_name
FROM customers c
LEFT JOIN payments p on p.customer_id = c.customer_id
  AND p.payment_status = 1 -- Payment condition here!
LEFT JOIN branches b ON b.customer_id = c.customer_id
LEFT JOIN managers m ON m.branch_id = b.branch_id
WHERE c.customer_status = 1
GROUP BY
    c.customer_id,
    c.customer_companyname,
    c.customer_status,
    b.branch_id,
    b.branch,
    m.manager_id,
    m.manager_name

两个要点:

  • The reason you can't have the payments condition in the WHERE clause is that missed joins have nulls in the joined column, so the test on payment status won't be true and you'll filter out customers with no payments with status 1, instead if returning 0 for the sum. By putting the condition into the join condition, it only matches suitable rows, but will still allow the customer row to be returned without any.
  • It's OK to have non-key related conditions on a join condition. Most people don't realise this. It's good to keep in mind.

Note that your join conditions look incorrect. I would expect that branch should match on c.branch_id = b.brach_id and similarly for manager, but I'll leave that to you to sort out.

于 2014-06-03T22:32:38.767 回答
1
select c.customer_id,c.customer_companyname,c.customer_status,SUM(p.payment_amount) as total_received from customers c
 left join payments p on (p.customer_id=c.customer id and p.payment_status=1)
 left join branches b on (b.customer_id=c.customer_id) 
 left join managers m on (m.branch_id=b.branch_id) 
 where customer_status=1 group by p.customer_id order by p.customer_id

这是一个复杂的查询,我没有您的数据库可以比较,但我认为您的解决方案是将所有表连接到客户,然后按您要求和的表分组。

这是一个跨表聚合的示例,以防我的代码中有漏洞:http ://www.artfulsoftware.com/infotree/qrytip.php?id=105

于 2014-06-03T22:43:30.593 回答