【问题标题】:Remove duplicates after merge in SQL在 SQL 中合并后删除重复项
【发布时间】:2021-04-25 02:53:45
【问题描述】:

我有三个表(t1、t2 和 t3)。见下文:

第一张桌子:

ID          AMOUNT
1              100
2              50

第二张桌子:

ID          TYPE
1              A
2              B

第三张表:

TYPE          GRADE
A              X
B              Y
B              Z

我们首先通过 ID 进行内连接 t1 和 t2,然后通过 TYPE 进行内连接 t2 和 t3。

SELECT 
t1.ID as ID, 
t1.AMOUNT as AMOUNT, 
t2.TYPE as TYPE,
t3.GRADE as GRADE
FROM t1 
INNER JOIN t1 ON t1.ID=t2.ID
INNER JOIN t2 ON t2.TYPE=t3.TYPE

决赛桌

ID          AMOUNT          TYPE          GRADE
1              100           A            X   
2              50            B            Y 
2              50            B            Z

我需要按 ID 和 TYPE 检查重复,如果总记录> 1,我需要删除 GRADE = Z 的。

所以最终期望的输出应该是

ID          AMOUNT          TYPE          GRADE
1              100           A            X   
2              50            B            Y 

【问题讨论】:

  • WHERE GRADE <> 'Z' ???
  • 很好的建议,但是如果没有重复的记录的等级=z怎么办?这行不通。
  • FROM t1 INNER JOIN t1 ON t1.ID=t2.ID INNER JOIN t2 ON t2.TYPE=t3.TYPE

标签: sql join duplicates


【解决方案1】:

如果同一 ID 和 Type 的行数超过两行,会发生什么情况?查询应该返回除等级 Z 之外的所有值。使用下面的查询来实现。

我在您的查询中添加了一个名为“rownumber”的额外列,以根据 ID 和类型对每一行进行编号,并按等级排序。这意味着具有相同 ID 和 Type 的每一行将具有从 1 开始的序列号。此序列将按等级升序排列。 然后我使用了通用表表达式,在 where 子句中,我为每个 id 和类型(行号为 1)选择了第一行以及所有行号 >1 和等级 'z' 的行,以消除任何等级为“Z”的行" IT 和 Type 至少已经存在一行。

    create table t1 (ID          int ,AMOUNT int)
    insert into t1 values(1             , 100)
    insert into t1 values(2              ,50)
    
    create table t2(ID          int ,Type varchar(10))
    insert into t2 values(1,              'A')
    insert into t2 values(2              ,'B')
    
    
    
    Create table t3 ([Type] varchar(10), grade varchar(10))
    insert into t3 values('A',              'X')
    insert into t3 values('B',              'Y')
    insert into t3 values('B',              'Z')
    insert into t3 values('B',              'X')
    
    
with cte as(
SELECT 
t1.ID as ID, 
t1.AMOUNT as AMOUNT, 
t2.TYPE as TYPE,
t3.GRADE as GRADE,
row_number()over (partition by t1.id,t2.type  order by grade) rownumber
FROM t1 
INNER JOIN t2 ON t1.ID=t2.ID
INNER JOIN t3 ON t2.TYPE=t3.TYPE)
select id,AMOUNT,type,grade,rownumber from cte where rownumber=1 or (rownumber>1 and GRADE<>'Z')

【讨论】:

  • 谢谢,能否请您添加一个简单的过程说明?
  • 具体来说,这一行“row_number()over (partition by t1.id,t2.type order by grade) rn”。谢谢!
  • row_number() 是一个窗口函数,它根据 over() 条件为每一行生成数字。这是一个非常有用的功能。检查下面的链接docs.microsoft.com/en-us/sql/t-sql/functions/…
【解决方案2】:
SELECT 
t1.ID as ID, 
t1.AMOUNT as AMOUNT, 
t2.TYPE as TYPE,
MIN(t3.GRADE) as GRADE
FROM t1 
INNER JOIN t1 ON t1.ID=t2.ID
INNER JOIN t2 ON t2.TYPE=t3.TYPE
GROUP BY t1.ID,
t1.AMOUNT,
t2.TYPE

这样做是对 Grade 列执行聚合函数,然后消除其他列中的重复项。

【讨论】:

  • 谢谢!有没有办法在不使用 MIN 函数的情况下做到这一点?恐怕我的数据中的 GRADE 列包含的类别不仅仅是 X、Y、Z 等。
猜你喜欢
  • 1970-01-01
  • 2021-05-07
  • 2018-03-11
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2013-05-02
  • 2018-06-09
  • 2011-05-25
相关资源
最近更新 更多