23

2つのフィールドの組み合わせに対して一意である必要があるOracleデータベーステーブルに行がありますが、テーブルに一意の制約が設定されていないため、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

誰かが私が間違っていること、および/またはこれを解決する方法を提案できますか?

4

9 に答える 9

42
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
于 2010-08-17T15:21:14.003 に答える
12
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)
于 2010-08-17T15:21:16.860 に答える
2

クエリの書き直し

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) は、名前がテーブルとサブクエリの両方に表示される列を ing していたためだと思いselectます。dupesmytablet1

于 2010-08-17T15:19:02.090 に答える
2

初期選択の 3 つのフィールドを次のように変更します。

SELECT
t1.entity_id, t1.station_id, t1.obs_year
于 2010-08-17T15:19:26.577 に答える
1

メイン選択で列のテーブルを指定する必要があります。また、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
于 2010-08-17T16:03:57.180 に答える
1

ユニーク制約を含む新しいテーブルを作成し、失敗を無視して行ごとにデータをコピーすることはできませんか?

于 2010-08-17T15:19:02.857 に答える
0
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のコストを与えた

テーブルにインデックスが作成されていませんでした....

于 2013-12-03T04:29:54.970 に答える
0

3列の主キー制約があり、重複を見つける必要があったため、ここでの解決策の多くは面倒で理解しにくいと思いました。だからここにオプションがあります

SELECT id, name, value, COUNT(*) FROM db_name.table_name
GROUP BY id, name, value
HAVING COUNT(*) > 1
于 2019-05-02T20:23:53.923 に答える