Oracleデータベーステーブルには2つのフィールドの組み合わせに対して一意である行がありますが、テーブルに一意の制約が設定されていないため、SQLを使用して制約に違反するすべての行を見つける必要があります。残念ながら、私の貧弱なSQLスキルはタスクに応じていません。
私のテーブルには、entity_id、station_id、obs_yearの3つの関連する列があります。各行について、station_idとobs_yearの組み合わせは一意である必要があります。SQLクエリでフラッシュすることにより、これに違反する行があるかどうかを確認したいと思います。
私は次のSQLを試してみました( この前の質問 で提案されています)が、それはうまくいきません(曖昧に定義されたORA-00918列を取得します):
SELECT
entity_id, station_id, obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
誰かが私が間違っていること、および/またはこれを解決する方法を提案できますか?
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
FROM mytable t
)
WHERE rn > 1
SELECT entity_id, station_id, obs_year
FROM mytable t1
WHERE EXISTS (SELECT 1 from mytable t2 Where
t1.station_id = t2.station_id
AND t1.obs_year = t2.obs_year
AND t1.RowId <> t2.RowId)
クエリの書き直し
SELECT
t1.entity_id, t1.station_id, t1.obs_year
FROM
mytable t1
INNER JOIN (
SELECT entity_id, station_id, obs_year FROM mytable
GROUP BY entity_id, station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
あいまいな列エラー(ORA-00918)は、名前がテーブルとサブクエリの両方に表示されるselect
ing列だったが、dupes
またはfrom mytable
(エイリアスはt1
)。
初期選択の3つのフィールドを変更して
SELECT
t1.entity_id, t1.station_id, t1.obs_year
メイン選択で列のテーブルを指定する必要があります。また、entity_idがmytableの一意のキーであり、重複の検出とは無関係であると仮定すると、dupesサブクエリでグループ化しないでください。
試してください:
SELECT t1.entity_id, t1.station_id, t1.obs_year
FROM mytable t1
INNER JOIN (
SELECT station_id, obs_year FROM mytable
GROUP BY station_id, obs_year HAVING COUNT(*) > 1) dupes
ON
t1.station_id = dupes.station_id AND
t1.obs_year = dupes.obs_year
一意の制約を含む新しいテーブルを作成してから、エラーを無視して、データを行ごとにコピーできませんでしたか?
SELECT *
FROM (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY station_id, obs_year ORDER BY entity_id) AS rn
FROM mytable t
)
WHERE rn > 1
by Quassnoiは、大きなテーブルに最も効率的です。私はコストのこの分析を持っていました:
SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
WHERE EXISTS (SELECT 1 from trn_refil_book b Where
a.dist_code = b.dist_code and a.book_date = b.book_date and a.book_no = b.book_no
AND a.RowId <> b.RowId)
;
1322341のコストを与えた
SELECT a.dist_code, a.book_date, a.book_no
FROM trn_refil_book a
INNER JOIN (
SELECT b.dist_code, b.book_date, b.book_no FROM trn_refil_book b
GROUP BY b.dist_code, b.book_date, b.book_no HAVING COUNT(*) > 1) c
ON
a.dist_code = c.dist_code and a.book_date = c.book_date and a.book_no = c.book_no
;
1271699のコストを与えた
ながら
SELECT dist_code, book_date, book_no
FROM (
SELECT t.dist_code, t.book_date, t.book_no, ROW_NUMBER() OVER (PARTITION BY t.book_date, t.book_no
ORDER BY t.dist_code) AS rn
FROM trn_refil_book t
) p
WHERE p.rn > 1
;
1021984のコストを与えた
テーブルはインデックス付けされていませんでした。
_ SELECT entity_id, station_id, obs_year
FROM mytable
GROUP BY entity_id, station_id, obs_year
HAVING COUNT(*) > 1
_
SELECTとGROUP BYの両方で重複を見つけるためにフィールドを指定します。
_GROUP BY
_を使用して、指定された列に基づいて他の行と一致する行を検索します。 HAVING COUNT(*) > 1
は、1回以上発生する(したがって重複している)行の表示のみに関心があることを示しています
3列の主キー制約があり、重複を見つける必要があるため、ここでの解決策の多くは面倒で理解しにくいと思いました。ここにオプションがあります
SELECT id, name, value, COUNT(*) FROM db_name.table_name
GROUP BY id, name, value
HAVING COUNT(*) > 1