用于在任何表中查找重复行的SQL查询

时间:2011-07-13 18:32:21

标签: sql tsql

我正在寻找与架构无关的查询。也就是说,如果我有一个users表或purchases表,那么查询应该能够同时捕获任一表中的重复行而不进行任何修改(除了from子句,疗程)。

我正在使用T-SQL,但我猜应该有一个通用的解决方案。

4 个答案:

答案 0 :(得分:8)

我相信这对你有用。请记住,CHECKSUM()不是100%完美 - 理论上可以在这里得到误报(我认为),但是否则你可以改变表名,这应该有效:

;WITH cte AS (
    SELECT
        *,
        CHECKSUM(*) AS chksum,
        ROW_NUMBER() OVER(ORDER BY GETDATE()) AS row_num
    FROM
        My_Table
)
SELECT
    *
FROM
    CTE T1
INNER JOIN CTE T2 ON
    T2.chksum = T1.chksum AND
    T2.row_num <> T1.row_num

需要ROW_NUMBER(),以便您可以通过某种方式区分行。它需要ORDER BY并且不能是常量,因此GETDATE()是我的解决方法。

只需更改CTE中的表名称即可,无需拼写列。

答案 1 :(得分:2)

我仍然对“检测它们可能是什么”感到困惑,但我会试一试。

排除它们很容易

e.g。

SELECT DISTINCT * FROM USERS

但是,如果您只想包含它们,并且所有字段都是重复的

SELECT 
   [Each and every field]
FROM
   USERS
GROUP BY
   [Each and every field]
HAVING COUNT(*) > 1  

你只能使用(*)就无法逃脱,因为你不能GROUP BY * 所以你的评论中的这个要求很难

  

与模式无关的意味着我不想指定所有列   在查询中

除非你想使用动态SQL并阅读sys.columnsinformation_schema.columns

中的列

例如

DECLARE @colunns nvarchar(max)
SET  @colunns = ''

SELECT @colunns = @colunns  + '[' +  COLUMN_NAME  +'], ' 
FROM INFORMATION_SCHEMA.columns  
WHERE table_name = 'USERS'

SET  @colunns  = left(@colunns,len(@colunns ) - 1)


DECLARE @SQL nvarchar(max)
SET @SQL = 'SELECT '  + @colunns 
          + 'FROM  USERS' + 'GROUP BY ' 
          + @colunns 
           + ' Having Count(*) > 1'


exec sp_executesql @SQL

请注意,如果您尚未

,请阅读此The Curse and Blessings of Dynamic SQL

答案 2 :(得分:1)

我在SQL Server中使用CTE完成了这项工作。

以下是如何删除欺骗的示例,但您应该能够轻松地对其进行调整以找到欺骗行为:

WITH CTE (COl1, Col2, DuplicateCount)
AS
(
    SELECT COl1,Col2,
    ROW_NUMBER() OVER(PARTITION BY COl1,Col2 ORDER BY Col1) AS DuplicateCount
    FROM DuplicateRcordTable
)
DELETE
FROM CTE
WHERE DuplicateCount > 1
GO

以下是我获得SQL的文章的链接:

http://blog.sqlauthority.com/2009/06/23/sql-server-2005-2008-delete-duplicate-rows/

答案 3 :(得分:0)

我最近正在研究同样的问题并注意到这个问题。 我设法使用带有一些动态SQL的存储过程来解决它。这样您只需指定表名。它将从sys表中获取所有其他相关数据。

/*
This SP returns all duplicate rows (1 line for each duplicate) for any given table.

to use the SP:
exec [database].[dbo].[sp_duplicates] 
    @table = '[database].[schema].[table]'  

*/
create proc dbo.sp_duplicates @table nvarchar(50) as

declare @query nvarchar(max)
declare @groupby nvarchar(max)

set @groupby =  stuff((select ',' + [name]
                FROM sys.columns
                WHERE object_id = OBJECT_ID(@table)
                FOR xml path('')), 1, 1, '')

set @query = 'select *, count(*)
                from '+@table+'
                group by '+@groupby+'
                having count(*) > 1'

exec (@query)