我需要有效地获取所有重复条目的整行

I need to get the whole row for all duplicate entries efficiently

互联网!我是 SQL 的新手,我需要获取某些字段中包含重复信息的所有行,并让它们显示在其他重复项旁边(按重复项分组)。

例如,假设我有一个 table 列:

A、B、C、D、E、F、G

我希望能够获取所有条目(整行),其中 B、C、D 和 E 与另一个条目共享相同的值,并在原始条目旁边显示重复项。 我已经有了一个解决方案,但效率低得可怕。我正在努力改善我在这里的 运行宁时间

我最初的解决方案是这样的:

    SELECT TOP 1000 
    A,
    B,
    C,
    D,
    E,
    F,
    G
    FROM tbl_myTable
    WHERE (B+C+D+E+F+G) IN (
        SELECT                                  
            B+C+D+E+F+G                 
        FROM                                    
            tbl_myTable                             
        GROUP BY                                    
            B,C,D,E,F,G                 
        HAVING COUNT(*) > 1 
    )

    ORDER BY B,C,D,E,F,G ASC

这给了我想要的结果,但它太慢了(花了 15 分钟才到达 运行)。我用临时 table 修改了我的解决方案,并使用此脚本将时间缩短到 运行ning 的 5 分钟:

    --Drop the temp table if it exists.
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL
DROP TABLE #Temp1

SELECT                              
     B+C+D+E+F+G AS CompareString       
 INTO #Temp1
 FROM tbl_myTable                           
 GROUP BY                                   
 B,C,D,E,F,G                
 HAVING COUNT(*) > 1

 SELECT TOP 1000 
 A,
 B,
 C,
 D,
 E,
 F,
 G
 FROM tbl_myTable
 WHERE (B+C+D+E+F+G) IN (
     SELECT * FROM #Temp1
 )
 ORDER BY B,C,D,E,F,G ASC

五分钟似乎还是很长。有没有更快的方法来做到这一点?我是 SQL 的新手,所以如果我做的不好,请告诉我!谢谢!

没有实际数据,我不得不在这里做一些假设。

首先,我假设您的字母字段都是文本类型,并且您使用 + 连接而不是添加数值(否则当 A = 1 B = 2 和 C = 3 时 A+B+C = 6以及当 A=2 B=3 和 C=1 时,这将不匹配)。

接下来我假设每行都有一个关键字段,但您的示例中没有。类似于 tbl_myTable.MyTableKey bigint IDENTITY (1,1) NOT NULL.

假设所有这些,我会尝试...

SELECT
    [BaseTable].MyTableKey AS [Original Record],
    [DupCheckTable].MyTableKey AS [Duplicate Record]
FROM
    tbl_myTable [BaseTable]
    LEFT OUTER JOIN tbl_myTable [DupCheckTable] ON 
            [BaseTable].A = [DupCheckTable].A
            AND
            [BaseTable].B = [DupCheckTable].B
            AND
            --... repeat for each actual field
            --AND
            [BaseTable].G = [DupCheckTable].G
            AND
            [BaseTable].MyTableKey  < [DupCheckTable].MyTableKey  --the less than operator prevents you from getting each match twice
WHERE
    [DupCheckTable].MyTableKey IS NOT NULL

我认为这会 运行 更快,因为您可以使用 table 键,它可能已编入索引,作为连接的一部分。此外,您可以将您的(或我的)任何查询提供给 Tuning Advisor,以查看它认为对统计数据和索引行有何帮助。

我会这样做:

with cte as (
   SELECT *
      , count(*) over (partition by B, C, D, E, F, G) as cnt
      , dense_rank() over (order by B, C, D, E, F, G) as grp
   FROM STI.[dbo].[tbl_Consignee]
)
select * 
from cte
where cnt > 1
order by grp

本质上,dense_rank() 调用为每个唯一的元组提供了一个标识符(因此您可以使用 order by 子句将重复项并排放置)并且计数计算每组的行数。