【问题标题】:Full Outer Join not working in MySql完全外部联接在 MySql 中不起作用
【发布时间】:2013-09-08 07:12:20
【问题描述】:

我想知道 MySQL 中 Full Outer Join 的替代方案。我知道它可以通过联合来完成,但它不起作用,因为我的要求并不复杂,我希望如此。我有两个表 master(branch_id,purchase_mindate,purchase_billvalue) 和 transfer(branch_id,tra_gtr_date,tra_travalue) ,其中两个 id 字段几乎相同。现在我需要通过加入两个带有条件的表来获取值 id,sum(billvalue),sum(travalue)

  1. Mindate=当前日期
  2. Gtrdate=当前日期
  3. 如果主表没有任何值,但传输表包含,则必须包含传输的值
  4. 如果 master 的表包含 value 但 transfer 没有,则必须显示 master 的 value。

我尝试了联合、加入等,但没有任何帮助

我使用了以下查询,

select purchase_master.branch_id, sum(purchase_billvalue) as billvalue, sum(tra_value) as travalue 

from purchase_master 
join purchase_transfer on purchase_master.branch_id=purchase_transfer.branch_id 
where purchase_mindate=CURDATE() and tra_gtr_date=CURDATE() 
group by branch_id

仅当两个表包含当前日期时,我才会获取值,但如果一个表具有而另一个表没有,则我不会获取任何值

我附上了表格的屏幕截图。

  1. 主表

  2. 转表

我尝试了下面的查询,但结果为空,

select pm.branch_id,pm.purchase_billvalue, pt.tra_value from purchase_master as pm
left outer join purchase_transfer as pt on pm.branch_id=pt.branch_id
where pm.purchase_mindate=CURDATE() and pt.tra_gtr_date=CURDATE()
union
select pm.branch_id,pm.purchase_billvalue, pt.tra_value from purchase_master as pm
right outer join purchase_transfer as pt on pm.branch_id = pt.branch_id
where pm.purchase_mindate=CURDATE() and pt.tra_gtr_date=CURDATE()

我需要结果为 sum(billvalue) sum(travalue) group by branch_id,

  1. 如果两个表包含当前日期数据
  2. 如果任何一个包含当前日期数据

【问题讨论】:

  • 架构、输入数据、预期结果。基本练习....
  • 你说的是什么意思...两个id字段几乎一样?它们是否相同?
  • 只是一样,它就像外键一样工作。
  • @Ajeesh 你能发布示例数据(每个表只有几行)和所需的输出吗?
  • @Ajeesh 这个样本数据的期望输出是什么?

标签: mysql sql outer-join


【解决方案1】:

因为每个 branch_id 两个表都不止一行,所以您需要首先 GROUP BY branch_id - 在每个表中单独 - 然后模拟 FULL JOIN,或者使用 UNION ALL 和另外一个 GROUP BY 或使用两个子查询,一个带有LEFT,一个带有RIGHT 外连接。

第一种(GROUP BY单独,然后UNION ALL加上GROUP BY)方式:

SELECT branch_id, 
       SUM(purchase_billvalue) AS purchase_billvalue, 
       SUM(tra_value) AS tra_value
FROM
  ( SELECT branch_id, 
           SUM(purchase_billvalue) AS purchase_billvalue,
           NULL AS tra_value
    FROM purchase_master
    WHERE purchase_mindate = CURDATE()
    GROUP BY branch_id
  UNION ALL
    SELECT branch_id, 
           NULL, 
           SUM(tra_value)
    FROM purchase_transfer  
    WHERE tra_gtr_date = CURDATE()
    GROUP BY branch_id
) AS u
GROUP BY branch_id ;

@peterm's answer 中提供了第三种方法 - 这可能是最有效的方法(但要进行测试!)。首先执行UNION(不是UNION ALL)以从两个表中查找所有不同的branch_id,然后执行2 个LEFT 连接到已分别执行GROUP BY branch_id 的派生表。

【讨论】:

    【解决方案2】:

    你可以这样做

    SELECT i.branch_id, 
           m.purchase_billvalue billvalue, 
           t.tra_travalue       travalue
      FROM
    (
        SELECT branch_id
          FROM master
         WHERE purchase_mindate = CURDATE()
         UNION
        SELECT branch_id
          FROM transfer  
         WHERE tra_gtr_date = CURDATE()
    ) i LEFT JOIN 
    (
      SELECT branch_id, SUM(purchase_billvalue) purchase_billvalue
        FROM master 
       WHERE purchase_mindate = CURDATE()
       GROUP BY branch_id
    ) m
        ON i.branch_id = m.branch_id LEFT JOIN 
    (
      SELECT branch_id, SUM(tra_travalue) tra_travalue
        FROM transfer  
       WHERE tra_gtr_date = CURDATE()
       GROUP BY branch_id
    ) t
        ON i.branch_id = t.branch_id
    

    示例输出(基于您的屏幕截图并假设所有显示行的两个表中的日期值都相等):

    | BRANCH_ID |比尔价值 |旅游 | |-----------|------------|----------| | 2 | 72580.61 | 119947 | | 3 | (空) | 9940 |

    这里是SQLFiddle演示

    【讨论】:

    • 我认为这不能满足要求 3 和 4。ID 必须存在于两个表中才能正常工作。
    • @peterm 我在尝试编码时收到类似“字段列表”中的未知列“t.tra_travalue”之类的错误
    • 这意味着您的代码中有一个 typo(例如,您为 transfer 表提供了不同的(t 除外)别名但没有更改它在选择子句中)。你看过我提供的有效的 sqlfiddle 示例吗?
    • @peterm 请看一下这个小提琴SQL Fiddle,结果不是预期的吗?应该没有什么travalue吧?
    • @Ajeesh 对。我已经更新了答案和 sqlfiddle。这是sqlfiddle,其中包含您的示例数据和更新的查询。它现在是否按预期工作?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    • 2014-12-18
    • 2017-08-04
    相关资源
    最近更新 更多