带有模糊列名的MySQL完全连接(联合)

时间:2014-04-15 11:20:29

标签: mysql sql select join union

我很失望的事实是MySQL在这么多年后仍然不支持FULL JOIN(为什么呢?)而且我必须使用UNION作为解决方法。说我遇到以下问题的问题。我有两张桌子作为例子:

计算机

id   userid   owner   cpu   
1    1        Jack    3.4
2    1        Jack    3.4
3    2        Sara    3.0

显示器

id   userid   owner   inch  
1    1        Jack    22    
2    1        Jack    22    
3    3        Mark    17    
4    4        Luke    32    

基本上我有一个计算机列表,其中包含已分配给所有者的规范。同样,我有一个带有规格的监视器列表,每个监视器分配给一个所有者。我希望按所有者将这两个表合并到这个结果中:

id   userid   owner   cpu   id   userid   owner   inch  
1    1        Jack    3.4   1    1        Jack    22
2    1        Jack    3.4   2    1        Jack    22
3    2        Sara    3.0   null null     null    null 
null null     null    null  3    3        Mark    17
null null     null    null  4    4        Luke    32

我可以使用此查询成功获得上述结果:

SELECT * FROM computers AS a
LEFT OUTER JOIN monitors AS o on a.owner = o.owner
UNION
SELECT * FROM computers AS a
RIGHT OUTER JOIN monitors AS o on a.owner = o.owner

问题是:

  1. 不希望在我的查询中使用快乐字符,不仅因为它效率不高,而且因为我只需要一些特定的列而不是全部
  2. 两个表都有不明确的列名(id,userid,owner),所以例如我似乎不能通过所有者进行ORDER BY。我知道我应该使用别名,但我不明白如何实现它
  3. 我必须使用WHERE语句,但由于列名不明确,我不知道如何实现它
  4. 现在总结我在伪查询中所说的内容:

      

    SELECT id AS a_id,userid AS a_userid,owner AS a_owner 但不是   cpu FROM计算机WHERE cpu = 3.4

    所有者加入UNION和JOIN:

      

    SELECT id AS b_id,userid AS b_userid,owner AS b_owner,inch AS b_inch FROM monitor WHERE inch = 22

    感谢您的时间。

2 个答案:

答案 0 :(得分:0)

模拟full outer join的另一种方法是使用子查询获取值的完整列表(owner)。然后使用left outer join引入其他值。根据您的描述:

select c.id as c_id, c.userid as c_userid, o.owner as owner,
       m.id as m_id, m.user_id as m_userid, m.inch
from (select owner from computers union
      select owner from monitors
     ) o left outer join
     computers c
     on o.owner = c.owner left outer join
     monitors m
     on o.owner = m.owner;

但是,您提到的查询不会生成这些结果。它会为“杰克”生成四个结果。

编辑:

我怀疑您希望在owneriduser_id上匹配:

select c.id as c_id, c.userid as c_userid, o.owner as owner,
       m.id as m_id, m.user_id as m_userid, m.inch
from (select owner, id, userid from computers union
      select owner, id, userid from monitors
     ) o left outer join
     computers c
     on o.owner = c.owner and o.userid = c.userid and o.id = c.id left outer join
     monitors m
     on o.owner = m.owner and o.userid = m.userid and o.id = m.id;

答案 1 :(得分:0)

这是cpu = 3.4和Inch = 22的完全外连接。首先获取所有计算机并加入监视器,然后获取所有监视器并加入计算机。主表标准在WHERE子句中,外连接标准在ON子句中。

SELECT a.userid, a.owner, a.id as computer_id, o.id as monitor_id, o.inch
FROM computers AS a
LEFT OUTER JOIN monitors AS o 
  ON a.owner = o.owner and a.userid = o.userid and o.inch = 22
WHERE a.cpu = 3.4
UNION
SELECT o.userid, o.owner, a.id as computer_id, o.id as monitor_id, o.inch
FROM monitors AS o
LEFT OUTER JOIN computers AS a
  ON a.owner = o.owner and a.userid = o.userid and a.cpu = 3.4
WHERE o.inch = 22;

但是,这可以通过仅添加第一个选择找不到的记录来加速,即没有匹配计算机的监视器。然后你可以使用UNION ALL代替UNION,它可以为dbms节省大量的工作。你只需要选择一个外部连接表的不可空的线圈。当它为NULL时,记录是外连接的。

SELECT a.userid, a.owner, a.id as computer_id, o.id as monitor_id, o.inch
FROM computers AS a
LEFT OUTER JOIN monitors AS o 
  ON a.owner = o.owner and a.userid = o.userid and o.inch = 22
WHERE a.cpu = 3.4
UNION ALL
SELECT o.userid, o.owner, a.id as computer_id, o.id as monitor_id, o.inch
FROM monitors AS o
LEFT OUTER JOIN computers AS a
  ON a.owner = o.owner and a.userid = o.userid and a.cpu = 3.4
WHERE o.inch = 22 and o.owner is null;