Di bawah ini adalah solusi berbasis set menggunakan CTE dan fungsi windowing.
ranked_matches
CTE memberikan peringkat kecocokan terdekat untuk setiap baris di TableA
bersama dengan peringkat kecocokan terdekat untuk setiap baris di TableB
, menggunakan index
nilai sebagai pemutus ikatan.
best_matches
CTE mengembalikan baris dari ranked_matches
yang memiliki peringkat terbaik (nilai peringkat 1) untuk kedua peringkat.
Terakhir, kueri luar menggunakan LEFT JOIN
dari TableA
ke best_matches
CTE untuk menyertakan TableA
baris yang tidak diberi kecocokan terbaik karena kecocokan penutupan sudah ditetapkan.
Perhatikan bahwa ini tidak mengembalikan kecocokan untuk baris TabelA indeks 3 yang ditunjukkan dalam hasil sampel Anda. Yang paling cocok untuk baris ini adalah indeks TableB 3, selisih 83. Namun, baris TableB itu lebih cocok dengan baris TableA indeks 2, selisih 14 jadi sudah ditetapkan. Tolong jelaskan pertanyaan Anda jika ini bukan yang Anda inginkan. Saya pikir teknik ini dapat disesuaikan.
CREATE TABLE dbo.TableA(
[index] int NOT NULL
CONSTRAINT PK_TableA PRIMARY KEY
, value int
);
CREATE TABLE dbo.TableB(
[index] int NOT NULL
CONSTRAINT PK_TableB PRIMARY KEY
, value int
);
INSERT INTO dbo.TableA
( [index], value )
VALUES ( 1, 123 ),
( 2, 245 ),
( 3, 342 ),
( 4, 456 ),
( 5, 608 );
INSERT INTO dbo.TableB
( [index], value )
VALUES ( 1, 152 ),
( 2, 159 ),
( 3, 259 );
WITH
ranked_matches AS (
SELECT
a.[index] AS a_index
, a.value AS a_value
, b.[index] b_index
, b.value AS b_value
, RANK() OVER(PARTITION BY a.[index] ORDER BY ABS(a.Value - b.value), b.[index]) AS a_match_rank
, RANK() OVER(PARTITION BY b.[index] ORDER BY ABS(a.Value - b.value), a.[index]) AS b_match_rank
FROM dbo.TableA AS a
CROSS JOIN dbo.TableB AS b
)
, best_matches AS (
SELECT
a_index
, a_value
, b_index
, b_value
FROM ranked_matches
WHERE
a_match_rank = 1
AND b_match_rank= 1
)
SELECT
TableA.[index] AS a_index
, TableA.value AS a_value
, best_matches.b_index
, best_matches.b_value
FROM dbo.TableA
LEFT JOIN best_matches ON
best_matches.a_index = TableA.[index]
ORDER BY
TableA.[index];
EDIT:
Meskipun metode ini menggunakan CTE, rekursi tidak digunakan dan oleh karena itu tidak terbatas pada rekursi 32K. Mungkin ada ruang untuk perbaikan di sini dari perspektif kinerja.