Níže je řešení založené na sadě pomocí CTE a funkcí oken.
ranked_matches
CTE přiřadí každému řádku v TableA
nejbližší hodnocení shody spolu s nejbližším hodnocením shody pro každý řádek v TableB
pomocí index
hodnotu jako nerozhodný výsledek.
best_matches
CTE vrací řádky z ranked_matches
které mají nejlepší hodnocení (hodnota pořadí 1) pro obě hodnocení.
Nakonec vnější dotaz používá LEFT JOIN
z TableA
na best_matches
CTE zahrnout TableA
řádky, kterým nebyla přiřazena nejlepší shoda, protože už byla přiřazena závěrečná shoda.
Všimněte si, že to nevrací shodu pro řádek tabulky A indexu 3 uvedený ve výsledcích vzorku. Nejbližší shoda pro tento řádek je index TableB 3, rozdíl 83. Tento řádek TableB se však blíže shoduje s řádkem indexu TableA 2, rozdíl 14, takže byl již přiřazen. Prosím, upřesněte svou otázku, pokud to není to, co chcete. Myslím, že tuto techniku lze odpovídajícím způsobem upravit.
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];
UPRAVIT:
Přestože tato metoda používá CTE, rekurze se nepoužívá, a proto není omezena na 32K rekurze. Zde však může být prostor pro zlepšení z hlediska výkonu.