【问题标题】:Union of Three tables without any duplicates minus one table in MysqlMysql中没有任何重复的三个表的并集减去一个表
【发布时间】:2019-07-09 15:56:39
【问题描述】:

表:2018

No  Email

1   Lilly@gmail.com

2   brens@gmail.com

3   susan@gmail.com

4   resh@gmail.com

表:2017

No   Email

1    chitta@gmail.com

2    resh@gmail.com

3    brens@gmail.com

4    minu@gmail.com

表:2016

No   Email

1     brens@gmail.com

2     chitta@gmail.com

3     lisa@gmail.com

4     monay@gmail.com

5     many@gmail.com

表:2019

No   Email

1    brens@gmail.com

2    chitta@gmail.com

3    rinu@gmail.com

4    emma@gmail.com

我需要执行表 2018,2017,2016 的联合,没有任何重复的电子邮件减去表 2019,结果应该看起来像

结果

No  Email

1    Lilly@gmail.com

2    susan@gmail.com

3    resh@gmail.com

4    minu@gmail.com

5   lisa@gmail.com

6   monay@gmail.com

7   many@gmail.com

Mysql 中没有减号操作。

select a.*from(select *from y2018 union select *from y2017 where not exists(select *from y2018 where y2018.email=y2017.email ) union select *from y2016 where not exists(select *from y2018 where y2018.email=y2016.email ))a LEFT OUTER JOIN y2019 b on a.email=b.email  where b.email is null ;

这给出了结果,但不会消除 (2017 union 2016) 中的重复项

有人帮帮我

【问题讨论】:

  • 为什么resh@gmail.com 在预期结果中?
  • @RaymondNijland (2018 UNION 2017 UNION 2016) resh@gmail.com 在表 2017 中
  • 这仍然无法解释,但当我阅读 “我需要执行 2018,2017,2016 表的联合时,没有任何重复的电子邮件减去 2019 表”
  • 我希望您也知道预期结果中的“否”列与您的真实数据无关?并且需要生成?

标签: mysql join union


【解决方案1】:

我需要执行 2018,2017,2016 表的联合,没有任何重复 电子邮件减去表 2019

最容易模拟/模拟减号/预期的是使用NOT IN()

查询

SELECT 
   (@ROW_NUMBER := @ROW_NUMBER + 1) AS 'No' 
 , unique_email.Email
FROM (

  SELECT 
    DISTINCT 
      years_merged.Email  
  FROM (

    SELECT 
     Email
    FROM 
     y2019
    UNION ALL
    SELECT 
     Email
    FROM 
     y2018
    UNION ALL
    SELECT 
     Email
    FROM
     y2017   
    UNION ALL
    SELECT 
     Email
    FROM 
     y2016     

  ) AS years_merged
  WHERE 
   years_merged.Email NOT IN(SELECT y2019.Email FROM y2019 ) 
  ORDER BY
   years_merged.Email ASC
) AS unique_email
CROSS JOIN (SELECT @ROW_NUMBER := 0) AS init
ORDER BY 
  @ROW_NUMBER ASC

结果

| No  | Email           |
| --- | --------------- |
| 1   | Lilly@gmail.com |
| 2   | lisa@gmail.com  |
| 3   | many@gmail.com  |
| 4   | minu@gmail.com  |
| 5   | monay@gmail.com |
| 6   | resh@gmail.com  |
| 7   | susan@gmail.com |

是的,顺序不同,但这是您能做的最好的事情,因为 SQL 标准将 SQL 表定义为无序排序..

demo

但是使用... LEFT JOIN ... ON ... WHERE .. IS NULL 进行模拟/模拟减/预期可能会比NOT IN() 优化得更好

demo

【讨论】:

  • 非常感谢,非常感谢您的帮助.. 如果表中存在其他列,例如名称和地址,并且需要显示所有字段,该怎么办
  • “还有一件事,如果表中存在其他列,例如名称和地址,并且需要显示所有字段” @NeenaSusan 将涉及另一个编写方法的“问题”之一是MySQL不支持DISTINCT ON(email), *(PostgreSQL)语法,否则它会很简单,但你可以simulate/emulate (post of mine)它..
  • 是否有在同一个查询中使用'group by'而不是distinct
  • "无论如何在同一个查询中使用 'group by' 而不是 distinct " 是的,但 GROUP BY 并不是真正设计为取消重复,理想情况下你应该只使用GROUP BY 当你打算在查询中使用Aggregate (GROUP BY) Function
  • 我明白了。你能告诉我其他方式吗
【解决方案2】:

我找到了一个更好的方法,创建一个视图并将查询的一部分保存在其中。它还有助于减少处理时间。

create view vm as select *from y2018 union select *from y2017 where not exists(select *from y2018 where y2018.email=y2017.email);

SELECT  a.*FROM(SELECT * FROM vm union select *from y2016 where not exists(select *from vm where vm.email=y2016.email))a LEFT JOIN y2019 b ON a.email=b.email where b.email is null;

这里的“vm”是视图

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-16
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 2016-05-15
    相关资源
    最近更新 更多