我正在寻找与架构无关的查询。也就是说,如果我有一个users
表或purchases
表,那么查询应该能够同时捕获任一表中的重复行而不进行任何修改(除了from
子句,疗程)。
我正在使用T-SQL,但我猜应该有一个通用的解决方案。
答案 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.columns
或information_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)