Mysql 使用左联接避免三个表中的笛卡尔积

Mysql 使用左联接避免三个表中的笛卡尔积,mysql,join,Mysql,Join,我有以下三个表格:- 客户(客户id、名称) 已完成(已完成id、客户id、已完成) 目标(目标id、客户id、目标) 在编写以下查询时,由于笛卡尔积,我得到了错误的输出:- SELECT C.name customer, SUM(A.achieved) achived, SUM(T.target) target FROM customers C LEFT JOIN achieved A ON C.customer_id = A.customer_id LEFT JOIN target T ON

我有以下三个表格:-

  • 客户(客户id、名称)
  • 已完成(已完成id、客户id、已完成)
  • 目标(目标id、客户id、目标)
  • 在编写以下查询时,由于笛卡尔积,我得到了错误的输出:-

    SELECT C.name customer, SUM(A.achieved) achived, SUM(T.target) target
    FROM customers C
    LEFT JOIN achieved A
    ON C.customer_id = A.customer_id
    LEFT JOIN target T
    ON C.customer_id = T.customer_id 
    GROUP BY customer
    

    使用LEFT join获得正确结果的正确方法是什么?

    您也可以尝试一下

    SELECT C.name customer, SUM(A.achieved) achived, SUM(T.target) target
    FROM customers C,achieved A,target T
    WHERE C.customer_id = A.customer_id 
          AND C.customer_id = T.customer_id 
          AND A.customer_id = T.customer_id
    GROUP BY C.customer
    

    我理解,因为您将
    已实现
    目标
    都加入到
    客户
    ,所以您得到的是
    已实现
    目标
    的无意义笛卡尔积

    您可以暂时删除
    SUM
    ,查看问题的原因。 如果没有
    SUM
    ,此查询将为您提供不必要的大结果集。使用
    SUM
    ,重复的值都会对求和产生影响,从而产生一个大于预期的值

    通过连接一个常量序列,可以强制MySQL将连接的表分开,如下所示

    SELECT C.name customer, SUM(A.achieved) achieved, SUM(T.target) target
    
    FROM customers C
    
    # Split every customer into two rows, joinType=1 vs. joinType=2
    LEFT JOIN (SELECT 1 AS joinItem UNION ALL SELECT 2) AS joinItems
    ON TRUE
    
    # Join achieved only where joinType=1 (will be NULL elsewhere)
    LEFT JOIN achieved A
    ON joinItem = 1 AND C.customer_id = A.customer_id
    
    # Join target only where joinType=2 (will be NULL elsewhere)
    LEFT JOIN target T
    ON joinItem = 2 AND C.customer_id = T.customer_id 
    
    GROUP BY customer
    
    现在,已实现目标和目标将不再相乘

    EXPLAIN
    应确认此问题仍然得到有效处理


    注意:最初,这会为每个匹配的“已实现”(目标数据为空)创建一个客户记录,并为每个匹配的“目标”(目标数据为空)创建一个单独的客户记录。然而,在这种情况下,
    分组依据
    会将每个客户的数据重新组合成一个记录,并提供我们想要的数据。

    从这个意义上讲,输出是错误的?您期望的输出是什么?为您的模式和示例数据提供sqlfiddle.com链接这不会产生与左连接相同的结果;它将排除没有任何目标或已实现(sic)记录的客户。