联合联接两个表(mysql)

时间:2018-12-15 01:07:27

标签: mysql sql

我想与另一个表(tableB)一起过滤表(tableA)。

我用于获取tableA结果的代码

select c.id, a.conversation_id, a.tag, c.email, c.created_at
from conversation c
right join (select * from conversation_tag
where tag = 'atlas-interest') as a
on a.conversation_id = c.id;

tableA

enter image description here

tableB

enter image description here

我想通过“电子邮件”外部连接这两个表。但是,我不断遇到语法问题
我的代码

select * from contact con
LEFT JOIN (select c.id, a.conversation_id, a.tag, c.email, c.created_at
from conversation c
right join (select * from conversation_tag
where tag = 'atlas-interest') as a
on a.conversation_id = c.id)) ON con.email = cc.email
UNION 
select * from con
RIGHT JOIN (select c.id, a.conversation_id, a.tag, c.email, c.created_at
from conversation c
right join (select * from conversation_tag
where tag = 'atlas-interest') as a
on a.conversation_id = c.id)) on con.email = cc.email;

我的另一个问题是,嵌套选择中的代码很容易变得混乱。是否有什么方法可以将tableA保存为变量,而仅在加入tableB时调用该变量?
我发现了这种方法SET @v1 := (SELECT COUNT(*) FROM user_rating);,但似乎一次只能保存一列。

3 个答案:

答案 0 :(得分:0)

您为子查询省略了cc别名。

SELECT * FROM contact con
LEFT JOIN (
     SELECT c.id, a.conversation_id, a.tag, c.email, c.created_at
     FROM conversation c
     RIGHT JOIN (
           SELECT * FROM conversation_tag
           WHERE tag = 'atlas-interest') AS a
     ON a.conversation_id = c.id
) AS cc ON con.email = cc.email
UNION 
     SELECT c.id, a.conversation_id, a.tag, c.email, c.created_at
     FROM conversation c
     RIGHT JOIN (
           SELECT * FROM conversation_tag
           WHERE tag = 'atlas-interest') AS a
     ON a.conversation_id = c.id
) AS cc ON con.email = cc.email

为避免重复子查询,您可以定义一个视图:

CREATE VIEW atlas_conversations AS
SELECT c.id, a.conversation_id, a.tag, c.email, c.created_at
FROM conversation c
RIGHT JOIN (
    SELECT * FROM conversation_tag
    WHERE tag = 'atlas-interest'
) AS a ON a.conversation_id = c.id;

那么您可以做:

SELECT *
FROM contact AS con
LEFT JOIN atlas_conversations AS cc ON con.email = cc.email
UNION
SELECT *
FROM contact AS con
RIGHT JOIN atlas_conversations AS cc ON con.email = cc.email

答案 1 :(得分:0)

这不是答案,但是评论太久。关于您的第一个查询...

select c.id, a.conversation_id, a.tag, c.email, c.created_at
from conversation c
right join (select * from conversation_tag
where tag = 'atlas-interest') as a
on a.conversation_id = c.id;

我们通常不使用RIGHT OUTER JOIN,因为它们比左外部联接更难读。毕竟,您选择conversation_tag行和tag = 'atlas-interest'行,然后将它们的conversation行加入外部。但是,为什么还要外部联接呢?没有相关的conversation_tag怎么可能有conversation?那将意味着数据库损坏(由于缺少外键)。

这就是说,您的查询应该只是:

select *
from conversation_tag ct
join conversation c on c.id = ct.conversation_id
where ct.tag = 'atlas-interest';

答案 2 :(得分:0)

您的第一个查询可以简化为:

select c.id, ct.conversation_id, ct.tag, c.email, c.created_at
from conversation c join
     conversation_tag ct
     on ct.conversation_id = c.id
where ct.tag = 'atlas-interest';

我怀疑您在conversation_id中是否有不匹配的conversation_tag

接下来,您希望在con上进行完全外部联接。为此,请收集所有电子邮件并使用left join

select ct.*, con.*
from ((select c.email
       from con c
      ) union  -- on purpose to remove duplicates
      (select c.email
       from conversation c join
            conversation_tag ct
            on ct.conversation_id = c.id
       where ct.tag = 'atlas-interest'
      )
     ) e left join
     con
     on e.email = con.email left join
     (select c.id, ct.conversation_id, ct.tag, c.email, c.created_at
      from conversation c join
           conversation_tag ct
           on ct.conversation_id = c.id
      where ct.tag = 'atlas-interest'
     ) ct
     on e.email = ct.email;

left join / right join / union骇客与真实的full join并不太相关。例如,它将删除重复项。