SQL-запрос для поиска повторяющихся строк в любой таблице - PullRequest
5 голосов
/ 13 июля 2011

Я ищу независимый от схемы запрос. То есть, если у меня есть таблица users или таблица purchases, запрос должен быть одинаково способен перехватывать дублирующиеся строки в любой таблице без каких-либо изменений (кроме, конечно, предложения from).

Я использую T-SQL, но я предполагаю, что должно быть общее решение.

Ответы [ 4 ]

8 голосов
/ 13 июля 2011

Я считаю, что это должно работать для вас. Имейте в виду, что 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, и оно должно работать без указания столбцов.

2 голосов
/ 13 июля 2011

Я все еще не понимаю, что такое «обнаружение их», но я попробую.

Исключить их легко

например

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

Обратите внимание, что вы должны прочитать это Проклятие и благословение динамического SQL , если вы еще не

1 голос
/ 13 июля 2011

Я сделал это, используя CTE в SQL Server.

Вот пример того, как удалять дубликаты, но вы сможете легко адаптировать его для поиска дубликатов:

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/

0 голосов
/ 22 мая 2017

Я недавно изучал ту же проблему и заметил этот вопрос. Мне удалось решить это с помощью хранимой процедуры с некоторым динамическим 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...