3

私は2つのテーブルAとBを持っています。どちらも同じ構造です。これら 2 つの間に一致するレコードが見つかります。ここにスクリプトがあります

CREATE TABLE HRS.A
(
F_1 NUMBER(5,0),
F_2 NUMBER(5,0),
F_3 NUMBER(5,0)
);

CREATE TABLE HRS.B
(
F_1 NUMBER(5,0),
F_2 NUMBER(5,0),
F_3 NUMBER(5,0)
);

INSERT INTO hrs.a VALUES (1,1000,2000);
INSERT INTO hrs.a VALUES (2,1100,8000);
INSERT INTO hrs.a VALUES (3,4000,3000);
INSERT INTO hrs.a VALUES (4,2000,5000);
INSERT INTO hrs.a VALUES (5,5000,3000);
INSERT INTO hrs.a VALUES (6,6000,6000);
INSERT INTO hrs.a VALUES (7,3000,7000);
INSERT INTO hrs.a VALUES (8,1100,9000);

INSERT INTO hrs.b VALUES (1,4000,2000);
INSERT INTO hrs.b VALUES (2,6000,8000);
INSERT INTO hrs.b VALUES (3,1000,3000);
INSERT INTO hrs.b VALUES (4,2000,5000);
INSERT INTO hrs.b VALUES (5,8000,3000);
INSERT INTO hrs.b VALUES (6,1100,6000);
INSERT INTO hrs.b VALUES (7,5000,7000);
INSERT INTO hrs.b VALUES (8,1000,9000);

一致するレコードを検索するには

SELECT a.F_1 A_F1, b.F_1 B_F1 FROM HRS.A, HRS.B WHERE A.F_2 = B.F_2

結果

A_F1 B_F1
3   1
6   2
1   3
4   4
8   6
2   6
5   7
1   8

ここで、両方の列の重複するエントリを個別に削除したいです。たとえば、A_F1 で 1 が繰り返されているため (B_F1 に関係なく)、行 # 3(1-3) と 8(1-8) が削除されます。現在、B_F1 で 6 が繰り返されているため (A_F1 に関係なく)、行 # 5(8-6) と 6(2-6) が削除されます。最終結果は

A_F1 B_F1
3   1
6   2
4   4
5   7

ここで最も重要な部分は、これら 2 つのテーブルにそれぞれ 500,000 レコードが含まれていることです。最初にこれらの一致するレコードを見つけて一時テーブルに挿入し、次に最初の列から重複を削除し、次に2番目の列から重複を削除してから、一時テーブルからすべてを選択しました。これは遅すぎます。どうすればこれをできるだけ早く達成できますか?

編集#1

次のステートメントを複数回実行して、各テーブルに 4096 レコードを生成しました

INSERT INTO hrs.a SELECT F_1 + 1, F_2 + 1, 0 FROM hrs.a;
INSERT INTO hrs.b SELECT F_1 + 1, F_2 + 1, 0 FROM hrs.b;

今、私はすべての答えを実行し、これらを見つけました

Rachcha     9.11 secs   OK
techdo      1.14 secs   OK
Gentlezerg  577  msecs  WRONG RESULTS
Justin      218  msecs  OK

@Justin でさえ、それぞれの 65,536 レコードに 37.69 秒かかりました (合計 = 131,072)

実際のレコード数は1,000,000であるため、より最適化された回答を待っています:)

ジャスティンの回答に基づくクエリの実行計画は次のとおりです

ここに画像の説明を入力

4

5 に答える 5

1

クエリ:

SQLFIDDLE例

SELECT a.f_1 AS a_f_1, 
       b.f_1 AS b_f_1
FROM a JOIN b ON a.f_2 = b.f_2
WHERE 1 = (SELECT COUNT(*)
           FROM a aa JOIN b bb ON aa.f_2 = bb.f_2
           WHERE aa.f_1 = a.f_1 )
AND 1 = (SELECT COUNT(*)
           FROM a aa JOIN b bb ON aa.f_2 = bb.f_2
           WHERE bb.f_1 = b.f_1 )

結果:

| A_F_1 | B_F_1 |
-----------------
|     3 |     1 |
|     6 |     2 |
|     4 |     4 |
|     5 |     7 |
于 2013-04-11T05:49:36.257 に答える
1

私には答えがあります。

ここでこのフィドルを参照してください。

次のコードを使用しました。

WITH x AS (SELECT a.f_1 AS a_f_1, b.f_1 AS b_f_1
             FROM a JOIN b ON a.f_2 = b.f_2)
SELECT *
  FROM x x1
 WHERE NOT EXISTS (SELECT 1
                     FROM x x2
                    WHERE (x2.a_f_1 = x1.a_f_1
                           AND x2.b_f_1 != x1.b_f_1)
                       OR (x2.a_f_1 != x1.a_f_1
                           AND x2.b_f_1 = x1.b_f_1)
                  )
;

編集

私は、 SQL fiddleで 14 ミリ秒以内に実行される次のコードを使用していました。共通テーブル式を削除したところ、クエリのパフォーマンスが向上したことがわかりました。

SELECT a1.f_1 AS a_f1, b1.f_1 AS b_f1
  FROM a a1 JOIN b b1 ON a1.f_2 = b1.f_2
 WHERE NOT EXISTS (SELECT 1
                     FROM a a2 JOIN b b2 ON a2.f_2 = b2.f_2
                    WHERE (a2.f_1 = a1.f_1
                           AND b2.f_1 != b1.f_1)
                       OR (a2.f_1 != a1.f_1
                           AND b2.f_1 = b1.f_1))
;

出力:

A_F_1   B_F_1
3           1
6           2
4           4
5           7
于 2013-04-11T05:39:45.967 に答える
1

@techdo の答えによると、これはもっと良いと思います:

select A_F1, B_F1 From(
  SELECT a.F_1 A_F1, b.F_1 B_F1,a.F_2,
    count(*) OVER(PARTITION BY A.F_2) C
  FROM HRS.A A, HRS.B B WHERE A.F_2 = B.F_2
)x 
where C=1 ;

複数の行が存在するのは、同じ f_2 によるものです。この SQL はカウントが 1 つしかありません..オーバーなので、膨大なデータがあるとおっしゃいましたが、これで少しは速くなると思います。

于 2013-04-11T06:06:23.463 に答える
0

これらのソリューションにはそれぞれ時間がかかります。最高のソリューション (ジャスティン) は、200 万件のレコードを返すことさえせずに、ほぼ 45 分かかりました。一致するレコードを一時テーブルに挿入してから重複を削除することになり、このデータセットを使用したこれらのソリューションよりもはるかに高速であることがわかりました。

于 2013-04-26T15:15:13.323 に答える