【问题标题】:SQL Joining two tables and removing the duplicates from the two tables but without loosing any duplicates from the tables itslefSQL连接两个表并从两个表中删除重复项,但不会丢失表本身的任何重复项
【发布时间】:2020-10-10 10:44:27
【问题描述】:

我想连接两个表并从两个表中删除重复项,但保留在第一个表中找到的所有重复值。

T1

Name
-----
A
A
B
C

T2

Name
----
A
D
E

预期结果

A - > FROM T1
A - > FROM T1
B
C
D
E

我尝试了union,但从两个表中删除了所有重复的“A”。

我怎样才能做到这一点?

【问题讨论】:

  • 所以如果T2 有两行B,你会想要A, A, B, B, C, D, E,即你想要文件中每个值重复次数最多的重复项数?
  • @Andreas 是的。这是正确的。不想从表本身中删除重复项。谢谢
  • @Rick707 。 . .你的问题有点不完整。它可以解释为只有第一个表有重复,我只想要一列。或者它可以被解释为确实有很多列,我不希望名称重复。或所有列重复。
  • 请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出尽可能少的代码,即您显示的代码可以通过您显示的代码扩展为不正常的代码。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask 暂停总体目标的工作,将代码砍到第一个表达式,没有给出你期望的内容,说出你期望的内容和原因。

标签: sql sql-server join duplicates union


【解决方案1】:

UNION ALL之前过滤T2

select col 
from T1
union all
select col 
from T2 
where not exists (select 1 from T1 where T1.col = T2.col)

【讨论】:

    【解决方案2】:

    假设您想要表中每个值的重复次数最多的重复项数,您可以使用ROW_NUMBER() 窗口函数来完成,以使用每个表中的重复集按其顺序消除重复项。

    SELECT Name FROM (
       SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
         FROM T1
       UNION
       SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
         FROM T2
    ) x
    ORDER BY Name
    

    要查看结果如何,我们将两个 B 行添加到 T2,然后执行以下操作:

    SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
      FROM T1
    
    Name  Row
    A     1
    A     2
    B     1
    C     1
    

    SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
      FROM T2
    
    Name  Row
    A     1
    B     1
    B     2
    D     1
    E     1
    

    现在UNION 他们没有ALL 来合并和消除重复:

    SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
      FROM T1
    UNION
    SELECT Name, ROW_NUMBER() OVER ( PARTITION BY Name ORDER BY Name ) AS Row
      FROM T2
    
    Name  Row
    A     1
    A     2
    B     1
    B     2
    C     1
    D     1
    E     1
    

    最后的查询就是去掉Row列并对结果进行排序,以确保升序。

    请参阅SQL Fiddle 进行演示。

    【讨论】:

      【解决方案3】:
      select * from T1
      union all 
      select * from T2 where name not in (select distinct name from T1)
      

      Sql Fiddle Demo

      【讨论】:

      • 使用distinct有多余的。
      【解决方案4】:

      您应该使用“union all”而不是“union”。 "union" 删除其他重复记录,而 "union all" 给出所有记录。

      对于你的结果,因为我们在“where”中过滤了表 2 中的相交,我们不需要“UNION ALL”

      select col1 from t1
      union
      select col1 from t2 where t2.col1 not in(select t1.col1 from t1)
      

      【讨论】:

      • UNION ALL 也会从 T2 返回 A。
      • yes."union all" 从 T1,T2 返回所有“A”。你想要什么?
      • 看一下题中的预期结果。
      【解决方案5】:

      我不知道下面的代码是不是好习惯但它正在工作

      select name from T1 
      
      UNION
      
      select name from T2 Where name not in (select name from T1)
      

      上述查询根据 T1 值过滤值,然后连接两个表值并显示结果。

      希望对你有帮助,谢谢。

      注意:获得结果并不是更好的方法,它会影响您的表现。

      我确定我在研究后会更新更好的解决方案

      【讨论】:

        【解决方案6】:

        您想要T1 中的所有名称以及T2 中的所有名称,T1 中的名称除外。
        所以你可以使用UNION ALL 来处理这两种情况,使用运算符EXCEPT 来过滤T2 的行:

        SELECT Name FROM T1
        UNION ALL
        (
          SELECT Name FROM T2
          EXCEPT
          SELECT Name FROM T1
        ) 
        

        请参阅demo
        结果:

        > | Name |
        > | :--- |
        > | A    |
        > | A    |
        > | B    |
        > | C    |
        > | D    |
        > | E    |
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-16
          • 2010-11-22
          • 1970-01-01
          • 1970-01-01
          • 2011-04-05
          • 2015-11-29
          • 2017-06-05
          相关资源
          最近更新 更多