これらの行に
したがって、重複する行は、一意の識別子列を除いて、すべての列でまったく同じ値を共有します。
サンプルデータ
例では、次のデータを使用します。
SELECT * FROM Dogs;
結果:
+-------+-----------+----------+ | DogId | FirstName | LastName | +-------+-----------+----------+ | 1 | Bark | Smith | | 2 | Bark | Smith | | 3 | Woof | Jones | | 4 | Ruff | Robinson | | 5 | Wag | Johnson | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +-------+-----------+----------+
最初の2行は重複しています(DogId
を除く) 列。これはテーブルの主キーであり、すべての行にわたって一意の値が含まれています)。最後の3行も重複しています(DogId
を除く) 列)。
主キー列は、重複する行がないことを保証します。これは通常、RDBMSでは良いことです。ただし、定義上、これは重複がないことを意味します。この場合、主キー列は増分番号であり、その値は意味を持たず、重要ではありません。したがって、 である列で重複を見つけたい場合は、その行を無視する必要があります。 重要。
オプション1
GROUP BY
を使用できます 句を使用して列を重要な列でグループ化し、 COUNT()
を使用します 同一の行数を返す関数:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName;
結果:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Ruff | Robinson | 1 | | Wag | Johnson | 3 | | Woof | Jones | 1 | +-----------+----------+-------+
クエリから主キー列を除外することで、主キー列を除外することができました。
結果は、Bark Smithを含む2つの行と、WagJohnsonを含む3つの行があることを示しています。これらは重複しています(またはWag Johnsonの場合は3回)。他の2つの行には重複がありません。
オプション2
HAVING
を使用すると、重複していないものを出力から除外できます。 条項:
SELECT
FirstName,
LastName,
COUNT(*) AS Count
FROM Dogs
GROUP BY FirstName, LastName
HAVING COUNT(*) > 1;
結果:
+-----------+----------+-------+ | FirstName | LastName | Count | +-----------+----------+-------+ | Bark | Smith | 2 | | Wag | Johnson | 3 | +-----------+----------+-------+
オプション3
連結された列の重複をチェックすることもできます。たとえば、CONCAT()
を使用できます 2つの列を連結する関数は、DISTINCT
を使用します キーワードを使用して個別の値を取得し、COUNT()
を使用します カウントを返す関数:
SELECT
DISTINCT CONCAT(FirstName, ' ', LastName) AS DogName,
COUNT(*) AS Count
FROM Dogs
GROUP BY CONCAT(FirstName, ' ', LastName);
結果:
+---------------+-------+ | DogName | Count | +---------------+-------+ | Bark Smith | 2 | | Ruff Robinson | 1 | | Wag Johnson | 3 | | Woof Jones | 1 | +---------------+-------+
オプション4
ROW_NUMBER()
を使用できます PARTITION BY
で機能する 条項:
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs;
結果:
+-------+-----------+----------+------------+ | DogId | FirstName | LastName | Row_Number | +-------+-----------+----------+------------+ | 1 | Bark | Smith | 1 | | 2 | Bark | Smith | 2 | | 4 | Ruff | Robinson | 1 | | 6 | Wag | Johnson | 1 | | 5 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | | 3 | Woof | Jones | 1 | +-------+-----------+----------+------------+>
これにより、重複するたびに増加する行番号を持つ新しい列が作成されますが、一意の行があると再びリセットされます。
この場合、結果はグループ化されていません。つまり、一意の識別子列を含む、重複する各行を確認できます。
オプション5
前の例を、より大きなクエリの一般的なテーブル式として使用することもできます。
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (
PARTITION BY FirstName, LastName
ORDER BY FirstName, LastName
) AS Row_Number
FROM Dogs
)
SELECT * FROM cte WHERE Row_Number <> 1;
結果:
+-------+-----------+----------+------------+ | DogId | FirstName | LastName | Row_Number | +-------+-----------+----------+------------+ | 2 | Bark | Smith | 2 | | 5 | Wag | Johnson | 2 | | 7 | Wag | Johnson | 3 | +-------+-----------+----------+------------+>
これにより、非重複が出力から除外され、各重複の1行が出力から除外されます。
このクエリは、重複排除操作の前兆として使用できます。重複を削除することにした場合、何が削除されるかを示すことができます。テーブルの重複排除を行うには、最後のSELECT *
を置き換えるだけです。 DELETE
を使用 。
オプション6
前の例と同じ出力を取得するためのより簡潔な方法は次のとおりです。
SELECT * FROM Dogs
WHERE DogId IN (
SELECT DogId FROM Dogs
EXCEPT SELECT MIN(DogId) FROM Dogs
GROUP BY FirstName, LastName
);
結果:
+-------+-----------+----------+ | DogId | FirstName | LastName | +-------+-----------+----------+ | 2 | Bark | Smith | | 6 | Wag | Johnson | | 7 | Wag | Johnson | +-------+-----------+----------+
この例では、独自の行番号を生成する必要はありません。
SELECT *
を置き換えることができます DELETE
を使用 重複を削除します。
オプション7
そして最後に、重複を返すための別のオプションがあります:
SELECT *
FROM Dogs d1, Dogs d2
WHERE d1.FirstName = d2.FirstName
AND d1.LastName = d2.LastName
AND d1.DogId <> d2.DogId
AND d1.DogId = (
SELECT MAX(DogId)
FROM Dogs d3
WHERE d3.FirstName = d1.FirstName
AND d3.LastName = d1.LastName
);
結果:
+-------+-----------+----------+-------+-----------+----------+ | DogId | FirstName | LastName | DogId | FirstName | LastName | +-------+-----------+----------+-------+-----------+----------+ | 2 | Bark | Smith | 1 | Bark | Smith | | 7 | Wag | Johnson | 5 | Wag | Johnson | | 7 | Wag | Johnson | 6 | Wag | Johnson | +-------+-----------+----------+-------+-----------+----------+