Nedenfor er en sæt-baseret løsning, der bruger CTE'er og vinduesfunktioner.
ranked_matches
CTE tildeler en tættest match-rangering for hver række i TableA
sammen med en tættest match-rangering for hver række i TableB
, ved hjælp af index
værdi som uafgjort.
best_matches
CTE returnerer rækker fra ranked_matches
der har den bedste rang (rangværdi 1) for begge rangeringer.
Endelig bruger den ydre forespørgsel en LEFT JOIN
fra TableA
til til best_matches
CTE for at inkludere TableA
rækker, der ikke blev tildelt et bedste match, fordi det lukkede match allerede er tildelt.
Bemærk, at dette ikke returnerer et match for indeks 3 TabelA række angivet i dine prøveresultater. Det lukkede match for denne række er TabelB-indeks 3, en forskel på 83. Denne TabelB-række er imidlertid et tættere match med TabelA-indeks 2-rækken, en forskel på 14, så den var allerede tildelt. Afklar venligst dit spørgsmål, hvis det ikke er det, du ønsker. Jeg tror, at denne teknik kan justeres i overensstemmelse hermed.
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:
Selvom denne metode bruger CTE'er, bruges rekursion ikke og er derfor ikke begrænset til 32K rekursioner. Der kan dog være plads til forbedring her set fra et præstationsperspektiv.