在MySQL中自行连接表时,在不同列中显示特定结果

时间:2016-09-26 16:01:47

标签: mysql sql mysql-workbench self-join

我有一个表email_activities_2,其中包含一个标题为“action_type”的列,其中结果可以是“已发送”,“打开”,“点击”等,每个电子邮件,每个recipient_id,每个操作有一条记录。例如,recipient_id 94607 for recipient_id 54有两行:一行是action_type被“发送”,第二行是“打开”。

我想要一个将在一行中返回的查询,其中action_type列列出两次,但在左侧,只显示action_type =“sent”,右列是action_type =“open”或“null”< / p>

这是我最接近我想要的东西:

select email2.email_id, email2.recipient_id, email2.action_type as sent, 
opens.action_type as opened
  from email_activities_2 email2 
  left join email_activities_2 opens on email2.id = opens.id
  where email2.action_type = "sent"
union all
select email2.email_id, email2.recipient_id, email2.action_type as sent, 
opens.action_type as opened
  from email_activities_2 email2
  right join email_activities_2 opens on email2.id = opens.id
  where opens.action_type = "open"
  order by recipient_id, email_id asc;

返回:

email_id    |   recipient_id   |  sent  |   opened

94607              54             sent      sent
94607              54             open      open
94981              54             sent      sent
98479              54             sent      sent
98479              54             open      open

当我想要的是:

email_id    |   recipient_id   |  sent  |   opened

94607              54             sent      open
94981              54             sent      NULL
98479              54             sent      open

这可能吗?我是SQL的新手,并且在我去的时候试图解决这个问题。

4 个答案:

答案 0 :(得分:0)

以下SQL应该为您完成这项工作:

Select email2.email_id,
       email2.recipient_id,
       MAX ( CASE WHEN email2.action_type = "sent" THEN email2.action_type  END ) As sent, 
       MAX (CASE WHEN opens.action_type = "open" THEN opens.action_type  END) As opened
  from email_activities_2 email2 
  left join email_activities_2 opens on email2.id = opens.id
  where email2.action_type = "sent" or opens.action_type = "open"
  group by email2.email_id
  order by recipient_id, email_id asc;

答案 1 :(得分:0)

我知道您希望获取所有已发送的电子邮件及其公开活动(如果已打开) 查询应该是:

select email2.email_id, email2.recipient_id, email2.action_type as sent, 
opens.action_type as opened
  from email_activities_2 email2 
  left join (
select * from  email_activities_2
where email_activities_2.action_type = "open" 
) as opens on email2.id = opens.id
  where email2.action_type = "sent"

答案 2 :(得分:0)

一种方法是条件聚合,不需要连接。

SELECT e.email_id
     , e.recipient_id
     , MAX(IF(e.action_type='sent',e.action_type,NULL)) AS sent
     , MAX(IF(e.action_type='open',e.action_type,NULL)) AS opened
  FROM email_activities_2 e
 WHERE e.action_type IN ('sent','open')
 GROUP
    BY e.email_id
     , e.recipient_id

GROUP BY子句将&#34;崩溃&#34;具有相同值的email_id和recipient_id的所有行成为一行。 SELECT子句中表达式中的条件测试将&#34;选择&#34;每个组的'open''sent'的值。 MAX聚合将选择要返回的最高非NULL值,并且只有在组中没有符合条件的行时才返回NULL。

此查询有可能返回如下行:

email_id    |   recipient_id   |  sent  |   opened
94999           54                NULL      open

如果有一行open但行没有sent

如果您需要删除这些行,可以添加一个HAVING子句:

HAVING MAX(IF(e.action_type='sent',e.action_type,NULL)) = 'sent'

如果要从表中返回email_id和recipient的所有值,即使没有action_type为'sent''open'的行,也可以完全省略WHERE子句。

答案 3 :(得分:0)

如果您只想显示已发送的电子邮件(或该表仅包含已发送的电子邮件),LEFT JOIN解决方案适用于两种类型。

select
    sent.email_id,
    sent.recipient_id,
    sent.action_type as sent,
    open.action_type as opened
from email_activities_2 sent
left join email_activities_2 open
    on  open.email_id = sent.email_id
    and open.recipient_id = sent.recipient_id
    and open.action_type = 'open'
where sent.action_type = 'sent';

Demo