web-dev-qa-db-ja.com

SQL Serverの重複行を削除する方法?

どうすればいいですかdelete duplicate rowsunique row idが存在しない場合

私のテーブルは

col1  col2 col3 col4 col5 col6 col7
john  1    1    1    1    1    1 
john  1    1    1    1    1    1
sally 2    2    2    2    2    2
sally 2    2    2    2    2    2

重複削除の後、次のものを残したままにします。

john  1    1    1    1    1    1
sally 2    2    2    2    2    2

私はいくつかのクエリを試してみましたが、私は望ましい結果が得られないので、それらは行IDに依存すると思います。例えば:

DELETE FROM table WHERE col1 IN (
    SELECT id FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)
324
Fearghal

CTEとROW_NUMBERを組み合わせると、どの行が削除(または更新)されているかを確認できるので、DELETE FROM CTE...SELECT * FROM CTEに変更するだけです。

WITH CTE AS(
   SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7],
       RN = ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col1)
   FROM dbo.Table1
)
DELETE FROM CTE WHERE RN > 1

DEMO (結果は異なります。私はそれがあなたの側のタイプミスが原因だと思います)

COL1    COL2    COL3    COL4    COL5    COL6    COL7
john    1        1       1       1       1       1
sally   2        2       2       2       2       2

この例では、col1のため、単一の列PARTITION BY col1で重複を判断します。複数の列を含める場合は、それらをPARTITION BYに追加するだけです。

ROW_NUMBER()OVER(PARTITION BY Col1, Col2, ... ORDER BY OrderColumn)
688
Tim Schmelter

私はSQL Serverのテーブルから重複した行を削除するためのCTEを好むでしょう

この記事に従うことを強くお勧めします:: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/

オリジナルのままに

WITH CTE AS
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN
FROM MyTable
)

DELETE FROM CTE WHERE RN<>1

元のままにせずに

WITH CTE AS
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3)
FROM MyTable)
 
DELETE CTE
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1)
128
Shamseer K

CTEROW_NUMBER()を使わなくても、group byとMAX関数を使ってレコードを削除できます。

DELETE
FROM MyDuplicateTable
WHERE ID NOT IN
(
SELECT MAX(ID)
FROM MyDuplicateTable
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3)
37
Aamir
DELETE from search
where id not in (
   select min(id) from search
   group by url
   having count(*)=1

   union

   SELECT min(id) FROM search
   group by url
   having count(*) > 1
)
13
Shoja Hamid

Microsoftは、重複を削除する方法についてきちんとしたガイドを持っています。チェックアウト http://support.Microsoft.com/kb/139444

簡単に言うと、削除する行が数行しかない場合に重複を削除する最も簡単な方法は次のとおりです。

SET rowcount 1;
DELETE FROM t1 WHERE myprimarykey=1;

myprimarykey は行の識別子です。

重複した行は2行しかないので、 rowcount を1に設定します。 3行複製した場合は、最初の2行を削除してテーブルt1に1行だけ残すように、 rowcount を2に設定します。

誰かに役立つことを願っています

6
oabarca

下記の削除方法もご覧ください。

Declare @table table
(col1 varchar(10),col2 int,col3 int, col4 int, col5 int, col6 int, col7 int)
Insert into @table values 
('john',1,1,1,1,1,1),
('john',1,1,1,1,1,1),
('sally',2,2,2,2,2,2),
('sally',2,2,2,2,2,2)

@tableという名前のサンプル表を作成し、それに所定のデータをロードしました。

enter image description here

Delete  aliasName from (
Select  *,
        ROW_NUMBER() over (Partition by col1,col2,col3,col4,col5,col6,col7 order by col1) as rowNumber
From    @table) aliasName 
Where   rowNumber > 1

Select * from @table

enter image description here

注:Partition by部分のすべての列を指定している場合、order byはそれほど重要ではありません。

私は知っている、3年前に質問がされている、そして私の答えはTimが投稿したものの別のバージョンだ。

5
Jithin Shaji

外部キーのように参照がない場合は、これを実行できます。概念実証をテストしてテストデータが複製されるとき、私はそれをたくさんします。

SELECT DISTINCT [col1]、[col2]、[col3]、[col4]、[col5]、[col6]、[col7]

INTO [newTable]

;

オブジェクトエクスプローラに移動し、古いテーブルを削除します。

新しいテーブルの名前を古いテーブルの名前に変更します。

4
Rhys

上記の提案された解決策を試した後に、それは小さな中型テーブルのために働く。非常に大きなテーブルに対しては、その解決策を提案できます。繰り返し実行されるためです。

  1. LargeSourceTableのすべての依存関係ビューを削除する
  2. sQL管理スタジオを使用して依存関係を見つけることができます。テーブルを右クリックして[依存関係の表示]をクリックします。
  3. テーブルの名前を変更します。
  4. sp_rename 'LargeSourceTable', 'LargeSourceTable_Temp'; GO
  5. もう一度LargeSourceTableを作成しますが、今度は重複を定義するすべての列を含む主キーを追加しますadd WITH (IGNORE_DUP_KEY = ON)
  6. 例えば:

    CREATE TABLE [dbo].[LargeSourceTable] ( ID int IDENTITY(1,1), [CreateDate] DATETIME CONSTRAINT [DF_LargeSourceTable_CreateDate] DEFAULT (getdate()) NOT NULL, [Column1] CHAR (36) NOT NULL, [Column2] NVARCHAR (100) NOT NULL, [Column3] CHAR (36) NOT NULL, PRIMARY KEY (Column1, Column2) WITH (IGNORE_DUP_KEY = ON) ); GO

  7. 新しく作成したテーブル用に最初にドロップしたビューをもう一度作成します。

  8. では、次のSQLスクリプトを実行すると、1ページに1,000,000行の結果が表示されます。1ページに表示される行数を変更して、結果をより頻繁に表示できます。

  9. 私はIDENTITY_INSERTをonとoffに設定したことに注意してください

SET IDENTITY_INSERT LargeSourceTable ON DECLARE @PageNumber AS INT, @RowspPage AS INT DECLARE @TotalRows AS INT declare @dt varchar(19) SET @PageNumber = 0 SET @RowspPage = 1000000select @TotalRows = count (*) from LargeSourceTable_TEMP

While ((@PageNumber - 1) * @RowspPage < @TotalRows )
Begin
    begin transaction tran_inner
        ; with cte as
        (
            SELECT * FROM LargeSourceTable_TEMP ORDER BY ID
            OFFSET ((@PageNumber) * @RowspPage) ROWS
            FETCH NEXT @RowspPage ROWS ONLY
        )

        INSERT INTO LargeSourceTable 
        (
             ID                     
            ,[CreateDate]       
            ,[Column1]   
            ,[Column2] 
            ,[Column3]       
        )       
        select 
             ID                     
            ,[CreateDate]       
            ,[Column1]   
            ,[Column2] 
            ,[Column3]       
        from cte

    commit transaction tran_inner

    PRINT 'Page: ' + convert(varchar(10), @PageNumber)
    PRINT 'Transfered: ' + convert(varchar(20), @PageNumber * @RowspPage)
    PRINT 'Of: ' + convert(varchar(20), @TotalRows)

    SELECT @dt = convert(varchar(19), getdate(), 121)
    RAISERROR('Inserted on: %s', 0, 1, @dt) WITH NOWAIT
    SET @PageNumber = @PageNumber + 1
End

SET IDENTITY_INSERT LargeSourceTable OFF

4
Moshe Taieb
-- this query will keep only one instance of a duplicate record.
;WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY col1, col2, col3-- based on what? --can be multiple columns
                                       ORDER BY ( SELECT 0)) RN
         FROM   Mytable)



delete  FROM cte
WHERE  RN > 1
2
Hasan Shouman
     SELECT DISTINCT * FROM TABLE;

これにより、重複する行がすべて削除され、個別の値(行)だけが表示されます。

1
Prince_Prajwal

重複レコードをフィールドに従ってグループ化してから、レコードの1つを保持して残りを削除する必要があります。例えば:

DELETE prg.Person WHERE Id IN (
SELECT dublicateRow.Id FROM
(
select MIN(Id) MinId, NationalCode
 from  prg.Person group by NationalCode  having count(NationalCode ) > 1
 ) GroupSelect
 JOIN  prg.Person dublicateRow ON dublicateRow.NationalCode = GroupSelect.NationalCode 
 WHERE dublicateRow.Id <> GroupSelect.MinId)
1
Hadi Salehy

あなたが一時的にテーブルに列を追加する能力を持っているなら、これは私のために働いた解決策でした:

ALTER TABLE dbo.DUPPEDTABLE ADD RowID INT NOT NULL IDENTITY(1,1)

次にMINとGROUP BYの組み合わせを使用してDELETEを実行します。

DELETE b
FROM dbo.DUPPEDTABLE b
WHERE b.RowID NOT IN (
                     SELECT MIN(RowID) AS RowID
                     FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
                     GROUP BY a.ITEM_NUMBER,
                              a.CHARACTERISTIC,
                              a.INTVALUE,
                              a.FLOATVALUE,
                              a.STRINGVALUE
                 );

DELETEが正しく実行されたことを確認します。

SELECT a.ITEM_NUMBER,
    a.CHARACTERISTIC,
    a.INTVALUE,
    a.FLOATVALUE,
    a.STRINGVALUE, COUNT(*)--MIN(RowID) AS RowID
FROM dbo.DUPPEDTABLE a WITH (NOLOCK)
GROUP BY a.ITEM_NUMBER,
    a.CHARACTERISTIC,
    a.INTVALUE,
    a.FLOATVALUE,
    a.STRINGVALUE
ORDER BY COUNT(*) DESC 

結果には、1より大きいカウントを持つ行が含まれていないはずです。最後に、rowid列を削除します。

ALTER TABLE dbo.DUPPEDTABLE DROP COLUMN RowID;
1
j.hull

https://support.Microsoft.com/ja-jp/help/139444/how-to-remove-duplicate-rows-from-a-table-in-sql-serverを参照して

重複を削除するという考えには、

  • a)重複していない行を保護する
  • b)重複しているとみなされた多数の行のうちの1つを保持します。

ステップバイステップ

  • 1)最初に、重複の定義を満たす行を特定し、それらを一時テーブルに挿入します。#tableAllと言います。
  • 2)#tableUniqueと言うように、一時テーブルに重複しない(単一行)または異なる行を選択します。
  • 3)#tableAllに参加するソーステーブルから削除して、重複を削除します。
  • 4)#tableUniqueのすべての行をソーステーブルに挿入します。
  • 5)#tableAllと#tableUniqueを削除します。
1
rajibdotnet
with myCTE
as

(
select productName,ROW_NUMBER() over(PARTITION BY productName order by slno) as Duplicate from productDetails
)
Delete from myCTE where Duplicate>1
1
Debendra Dash

使用してみてください:

SELECT linkorder
    ,Row_Number() OVER (
        PARTITION BY linkorder ORDER BY linkorder DESC
        ) AS RowNum
FROM u_links

enter image description here

1
Fezal halai
DECLARE @TB TABLE(NAME VARCHAR(100));
INSERT INTO @TB VALUES ('Red'),('Red'),('Green'),('Blue'),('White'),('White')
--**Delete by Rank**
;WITH CTE AS(SELECT NAME,DENSE_RANK() OVER (PARTITION BY NAME ORDER BY NEWID()) ID FROM @TB)
DELETE FROM CTE WHERE ID>1
SELECT NAME FROM @TB;
--**Delete by Row Number** 
;WITH CTE AS(SELECT NAME,ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB)
DELETE FROM CTE WHERE ID>1;
SELECT NAME FROM @TB;
0
Surinder Singh

巨大な(数百万件のレコード)テーブルから重複を削除するには、長い時間がかかる場合があります。削除するのではなく、選択した行の一時テーブルに一括挿入することをお勧めします。

--REWRITING YOUR CODE(TAKE NOTE OF THE 3RD LINE) WITH CTE AS(SELECT NAME,ROW_NUMBER() 
OVER (PARTITION BY NAME ORDER BY NAME) ID FROM @TB) SELECT * INTO #unique_records FROM 
CTE WHERE ID =1;
0
Emmanuel Bull

うわー、私はすべてのこれらの答えを用意することによってとても愚かだと感じます、彼らはすべてのCTEと臨時雇用者テーブルなどに関する専門家の答えのようです。

そしてそれを動かすために私がしたのはMAXを使ってID列を単純に集約することだけでした。

DELETE FROM table WHERE col1 IN (
    SELECT MAX(id) FROM table GROUP BY id HAVING ( COUNT(col1) > 1 )
)

注:重複を削除するには、一度に1セットの重複行しか削除されないため、複数回実行する必要があります。

0
messed-up

SQLサーバーでは多くの方法で実行できます。最も簡単な方法は、重複行テーブルから新しい一時テーブルに個別の行を挿入することです。次に、重複行テーブルからすべてのデータを削除し、次に示すように、重複のない一時テーブルからすべてのデータを挿入します。

select distinct * into #tmp From table
   delete from table
   insert into table
   select * from #tmp drop table #tmp

   select * from table

共通テーブル式(CTE)を使用して重複行を削除する

With CTE_Duplicates as

(id、nameを選択し、row_number()over(idによるパーティション、idによる名前の順序、nameによるテーブルのrowname)rownumber!= 1のCTE_Duplicatesから削除します

1ステップで情報を失うことなく重複行を削除する別の方法は、次のようなものです。

delete from dublicated_table t1 (nolock)
join (
    select t2.dublicated_field
    , min(len(t2.field_kept)) as min_field_kept
    from dublicated_table t2 (nolock)
    group by t2.dublicated_field having COUNT(*)>1
) t3 
on t1.dublicated_field=t3.dublicated_field 
    and len(t1.field_kept)=t3.min_field_kept
0