Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Kết nối trái với giá trị gần nhất mà không có trùng lặp

Dưới đây là một giải pháp dựa trên bộ sử dụng CTE và các chức năng cửa sổ.

ranked_matches CTE chỉ định xếp hạng đối sánh gần nhất cho mỗi hàng trong TableA cùng với xếp hạng đối sánh gần nhất cho mỗi hàng trong TableB , sử dụng index giá trị như một bộ ngắt kết nối.

best_matches CTE trả về các hàng từ ranked_matches có thứ hạng tốt nhất (giá trị xếp hạng 1) cho cả hai thứ hạng.

Cuối cùng, truy vấn bên ngoài sử dụng LEFT JOIN từ TableA tới best_matches CTE để bao gồm TableA các hàng không được chỉ định đối sánh tốt nhất do đối sánh đóng đã được chỉ định.

Lưu ý rằng điều này không trả về kết quả phù hợp cho hàng TableA chỉ số 3 được chỉ ra trong kết quả mẫu của bạn. Kết quả khớp cho hàng này là chỉ số TableB 3, hiệu số là 83. Tuy nhiên, hàng TableB đó gần khớp hơn với hàng chỉ mục TableA 2, chênh lệch 14 nên nó đã được chỉ định. Vui lòng làm rõ câu hỏi của bạn nếu đây không phải là điều bạn muốn. Tôi nghĩ rằng kỹ thuật này có thể được điều chỉnh cho phù hợp.

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];

CHỈNH SỬA:

Mặc dù phương pháp này sử dụng CTE, nhưng đệ quy không được sử dụng và do đó không giới hạn ở 32K đệ quy. Tuy nhiên, có thể có chỗ để cải thiện ở đây từ góc độ hiệu suất.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để kết nối Cakephp 1.3 với MS SQLServer 2008?

  2. Cách lưu trữ và truy xuất hình ảnh trong cơ sở dữ liệu máy chủ sql thông qua VB.NET

  3. Tính toán thời gian thời lượng SQL

  4. Tạo một DIE đối tượng trong SQL Server

  5. Sự cố khi tạo tệp .MDF từ Visual Studio 2010