सीटीई और विंडोिंग फ़ंक्शन का उपयोग करके एक सेट-आधारित समाधान नीचे दिया गया है।
ranked_matches
CTE TableA
. में प्रत्येक पंक्ति के लिए निकटतम मिलान रैंक प्रदान करता है TableB
. में प्रत्येक पंक्ति के लिए निकटतम मिलान रैंक के साथ , index
. का उपयोग करके टाई ब्रेकर के रूप में मूल्य।
best_matches
CTE ranked_matches
. से पंक्तियां लौटाता है जिनके पास दोनों रैंकिंग के लिए सर्वश्रेष्ठ रैंक (रैंक वैल्यू 1) है।
अंत में, बाहरी क्वेरी LEFT JOIN
. का उपयोग करती है TableA
. से करने के लिए best_matches
TableA
. को शामिल करने के लिए CTE क्लोज़ मैच को पहले ही असाइन किए जाने के कारण जिन पंक्तियों को सर्वश्रेष्ठ मिलान नहीं दिया गया था।
ध्यान दें कि यह आपके नमूना परिणामों में इंगित अनुक्रमणिका 3 TableA पंक्ति के लिए एक मिलान नहीं देता है। इस पंक्ति के लिए क्लोज मैच टेबलबी इंडेक्स 3 है, 83 का अंतर है। हालांकि, टेबलबी पंक्ति टेबलए इंडेक्स 2 पंक्ति के करीब है, 14 का अंतर है, इसलिए इसे पहले ही असाइन किया गया था। कृपया अपने प्रश्न को स्पष्ट करें यदि यह वह नहीं है जो आप चाहते हैं। मुझे लगता है कि इस तकनीक को तदनुसार बदला जा सकता है।
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];
संपादित करें:
हालांकि यह विधि सीटीई का उपयोग करती है, रिकर्सन का उपयोग नहीं किया जाता है और इसलिए 32 के रिकर्सन तक सीमित नहीं है। हालाँकि, प्रदर्शन के दृष्टिकोण से यहाँ सुधार की गुंजाइश हो सकती है।