インタビューで尋ねられた質問の1つは、
1つのテーブルには100レコードがあります。それらの50は重複しています。1つのクエリで、重複するレコードをテーブルから削除し、残りの50レコードを選択して表示することは可能ですか。
これは単一のSQLクエリで可能ですか?
ありがとう
SNA
インタビューで尋ねられた質問の1つは、
1つのテーブルには100レコードがあります。それらの50は重複しています。1つのクエリで、重複するレコードをテーブルから削除し、残りの50レコードを選択して表示することは可能ですか。
これは単一のSQLクエリで可能ですか?
ありがとう
SNA
SQL Serverでは、次のようなものを使用します
DECLARE @Table TABLE (ID INTEGER, PossibleDuplicate INTEGER)
INSERT INTO @Table VALUES (1, 100)
INSERT INTO @Table VALUES (2, 100)
INSERT INTO @Table VALUES (3, 200)
INSERT INTO @Table VALUES (4, 200)
DELETE FROM @Table
OUTPUT Deleted.*
FROM @Table t
INNER JOIN (
SELECT ID = MAX(ID)
FROM @Table
GROUP BY PossibleDuplicate
HAVING COUNT(*) > 1
) d ON d.ID = t.ID
OUTPUTステートメントは、削除されるレコードを示します。
アップデート:
上記のクエリは重複を削除し、残っている行ではなく、削除された行を提供します。それが重要な場合(全体として、残りの50行は削除された50行と同じである必要があります)、SQLServerの2008MERGE構文を使用してこれを実現できます。
Lieven's Answerは、削除された行を出力する方法の良い説明です。2つ追加したいと思います。
出力を表示する以外に何かをしたい場合は、指定できますOUTPUT INTO @Tbl
(@Tbl
削除される前に宣言したtable-varはどこにありますか)。
MAX
、、、MIN
またはその他の集計を使用すると、グループごとに1つの重複行のみを処理できます。重複が多い可能性がある場合は、次のSQLServer2005以降のコードが役立ちます。
;WITH Duplicates AS
(
SELECT
ID,
ROW_NUMBER() OVER (PARTITION BY DupeColumn ORDER BY ID) AS RowNum
)
DELETE FROM MyTable
OUTPUT deleted.*
WHERE ID IN
(
SELECT ID
FROM Duplicates
WHERE RowNum > 1
)
削除は削除された行の数のカウントのみを返すため、少なくともANSISQLではありそうにありません。