MySQL在多个表和where子句的左边连接

时间:2014-06-03 22:09:43

标签: mysql left-join right-join

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

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

混乱:

有两个WHERE条款,无论我放在哪里,我都会收到错误或JOIN无效

问题:

我有4张桌子:

customers - 即使没有付款,我也需要返回所有行,但仅限于customer_status = 1

payments - 包含与customer_id表关联的customers - 仅当payment_amount

时才需要从payment_status = 1返回的SUM

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

正如你所看到的,可口可乐和duff避风港已付款(没有付款表中的记录),但仍应列出

  • 因此,如果customer_status = 1
  • ,客户都应该出现
  • SUM付款只有在数据库和payment_status = 1
  • 分支机构和经理应该列出该客户,因为它总是在数据库中
  • 管理人员在其自己的桌子中,并且在不同的时间分配到不同的分支机构(因为我感觉有人可能会问)

已选择字段以及摘要

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

2 个答案:

答案 0 :(得分:2)

解决此问题的关键是将付款中的条件纳入加入条件

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

两个要点:

  • 您在WHERE子句中无法获得付款条件的原因是,错过的联接在已加入的列中具有空值,因此对付款状态的测试不会成立,您将进行过滤没有支付状态1的客户,而不是为总和返回0。通过将条件置于连接条件中,它只匹配合适的行,但仍允许返回客户行而不返回任何行。
  • 在连接条件下具有非关键相关条件是可以的。大多数人都没有意识到这一点。记住它是件好事。

请注意,您的加入条件看起来不正确。我希望分支在c.branch_id = b.brach_id上匹配,对于经理也是如此,但是我会留给你解决。

答案 1 :(得分: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