sql - 与最接近的值左连接,不重复

标签 sql sql-server sql-server-2008

我想在 MS SQL 中实现如下所示的效果,使用 2 个表并通过联接而不是迭代。

从表 A 中,我希望每一行都能从表 B 中识别出列表中最接近的值,并且选择值后,该值无法重复使用。如果您以前做过类似的事情,请帮忙。先感谢您! #SOreadyToAsk

enter image description here

最佳答案

下面是使用 CTE 和窗口函数的基于集合的解决方案。

ranked_matches CTE 为 TableA 中的每一行分配最接近的匹配排名,并为 TableB 中的每一行分配最接近的匹配排名,使用index 值作为决胜局。

best_matches CTE 返回 ranked_matches 中在两个排名中具有最佳排名(排名值 1)的行。

最后,外部查询使用从 TableAbest_matches CTE 的 LEFT JOIN 以包含 TableA 由于已分配关闭匹配而未分配最佳匹配的行。

请注意,这不会返回示例结果中指示的索引 3 TableA 行的匹配项。该行的最接近匹配是 TableB 索引 3,相差 83。但是,TableB 行与 TableA 索引 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];

编辑:

尽管此方法使用 CTE,但未使用递归,因此不限于 32K 递归。不过,从性能角度来看,这里可能还有改进的空间。

关于sql - 与最接近的值左连接,不重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32376682/

相关文章:

sql - Oracle Apex 5 错误,ORA-00907 : missing right parenthesis. 看不到缺少的括号?

asp.net - 如何将 Unicode 值作为 select 命令的参数传递

sql - Redshift : defining composite primary key

sql-server - 与我熟悉的 SELECT 语句不同

c# - 从 XML 更新插入 SQL Server 表

sql - 使用 case 语句创建触发器

sql - 如何优化 SQL 查询?

sql-server - 如何防止 SQL Server LocalDB 自动关闭?

java - 在 Hibernate 中设置参数值时指定字符串类型

sql-server-2008 - 用于替换字符串中某些变量的存储过程