【问题标题】:How to use row_number() to filter duplicates with multiple joins?如何使用 row_number() 过滤具有多个连接的重复项?
【发布时间】:2017-12-12 13:33:28
【问题描述】:

我需要过滤其他列底部的重复项。这是我正在尝试的代码。不幸的是,它不起作用,因为查询永远不会完成。

Select r1, r2, r3...,rb1,..., rc1,...  
From (
  Select *, ROW_NUMBER() OVER (PARTITION BY r1 order by r6 DESC) AS rownbr  
  From
    table1
    join table2 ON r2=rb1  
    Join table3 ON r6=rc1  
    Join table4 ON rx=rdx
) source  
Where  
  rownbr=1

有什么想法吗?

【问题讨论】:

  • 请扩展“不起作用”,也许有人会有一些想法
  • 查询永远不会结束。谢谢,尼克!
  • 你能分享一些样本数据和你想要得到的结果吗?这将使我们更容易为您提供帮助。
  • 我的猜测是您的联接不正确,因此您得到的记录太多以及“重复”。您绝对确定您的连接是正确的吗?您还应该为所有列名设置别名。 r1 和 r6 来自哪个表?你为什么不预先总结这个表,这样你就不会首先“加入”?
  • 当我运行没有“row_number() over() partition()”的代码时效果很好。当我使用 row_number() 时出现问题。使用 distinct 子句,我可以避免大多数重复项,但由于某种原因,每列中都有一些重复项不相等。这些是我需要避免的。

标签: sql-server duplicates row-number


【解决方案1】:

从语法上看,您的查询似乎是正确的。但是,在加入 4 个没有任何 where 子句的表时,您可能会尝试检索太多数据。可以改进查询的几个简单的事情是:

  • 仅在子查询中指定您需要的列。我很确定您不需要所有 4 个表中的所有内容。

  • 找出您是否可以更具体地处理您尝试获取的数据并在where 子句中使用它。例如,您可能只需要t1.createdate > '01-01-2016'

  • 如果这些仍然没有帮助,您将不得不开始研究索引。

    Select r1, r2, r3,rb1  
    From (
      Select * -- consider specifying only the columns that you need. Pretty sure you don't need every column from all 4 tables.
      , ROW_NUMBER() OVER (PARTITION BY r1 order by r6 DESC) AS rownbr  
      From table1 as t1
        join table2 as t2 ON t1.r2 = t2.rb1  
        Join table3 as t3 ON t3.r6 = t2.rc1  
        Join table4 as t4 ON t4.rx = t3.rdx
        where --may be something like date
        t1.createdate > '01-01-2016'
    ) source  
    Where  source.rownbr=1

【讨论】:

  • 感谢您的回答。你说得对,我只是使用第一次加入的列。我对这种方法不是很熟悉。我可以使用这样的东西吗? Select r1, r2, r3...,rb1,..., rc1,... From ( Select *, ROW_NUMBER() OVER (PARTITION BY r1 order by r6 DESC) AS rownbr From table1 join table2 ON r2=rb1) source FROM??? Join table3 ON r6=rc1 Join table 4 ON rx=rdx Where rownbr=1
  • 好吧,如果不知道您的表格和它们之间的关系,我很难说出它会有多大帮助。我要强调的一点是,因为您说查询没有完成,所以要具体并且只检索必要的数据。您是否真的对 table1 中的所有数据感兴趣,您没有任何符合条件的 where 子句? table1、table2、table3、table4一共有多少行?
  • 我会尽量使用你所说的一些属性!我会让你知道!非常感谢您的帮助。
【解决方案2】:

抱歉,还不能添加评论...

假设您的联接是正确的,为什么不直接使用 group by?

    Select r1, r2, r3...,rb1,..., rc1,...  
From (
  Select *
  From
    table1
    join table2 ON r2=rb1  
    Join table3 ON r6=rc1  
    Join table 4 ON rx=rdx
) source  
group by r1, r2, r3...,rb1,..., rc1,...  

【讨论】:

  • 感谢您的帮助杰!我会尽快尝试的!
  • group by 的问题是我需要处理很多列。
  • 问题是我处理的数据太多了,所以我使用了 FROM 子句中的 where 子句。非常感谢您的帮助。
  • GROUP BY 不适合查找或删除重复项。它将丢失结果表中的一些数据。这也是一个缓慢的过程。您可以了解四种删除重复项的方法。 sqlshack.com/…
【解决方案3】:

创建视图的可能解决方案:

CREATE VIEW TABLAEX
AS
select lastname, convert(varchar, birthdate, 103) "birthday",
CONVERT(varchar, hiredate, 103) "hiredate", city,  
(DATEDIFF(dd, birthdate, hiredate) + 1)   
-(DATEDIFF(wk, birthdate, hiredate) * 2)  
-(CASE WHEN DATENAME(dw, birthdate) = 'Sunday' THEN 1 ELSE 0 END)  
-(CASE WHEN DATENAME(dw, hiredate) = 'Saturday' THEN 1 ELSE 0 END) "working days",  
 case when city like '%London%' then 'vecino'  
 when city like '%Seattle%' then 'lejos'  
 else 'null'  
 end as val,   
 case when (DATEDIFF(dd, birthdate, hiredate) + 1)  
 -(DATEDIFF(wk, birthdate, hiredate) * 2)  
 -(CASE WHEN DATENAME(dw, birthdate) = 'Sunday' THEN 1 ELSE 0 END)  
 -(CASE WHEN DATENAME(dw, hiredate) = 'Saturday' THEN 1 ELSE 0 END) > 8000    then 'viejo'  
 else 'joven'  
 end as edad,
 ROW_NUMBER() OVER (PARTITION BY city order by hiredate) AS rownbr
 from   
 HR.Employees;
 GO
 SELECT DISTINCT lastname, birthday, hiredate, "working days", edad, val
 from TABLAEX
 WHERE rownbr=1;
 GO 
 DROP VIEW TABLAEX;       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 2015-09-17
    • 2019-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多