使用查找矩阵中最接近的值更新 table

Updating table with the closest value from a lookup matrix

TABLE 1

首先table是包含参考值的矩阵,像这样:

create table dm_matrix
(x float,
z float,
avgValue float)


insert into dm_matrix values (1,1, rand())
insert into dm_matrix values (1,2, rand())
...
insert into dm_matrix values (4,3, rand())
insert into dm_matrix values (4,4, rand())

创建这样的矩阵

z\x |  1  |  2  |  3  |  4  |
-----------------------------
  1 |  .1 |  .7 |  .3 |  .2 |
  2 |  .5 |  .1 |  .8 |  .6 |
  3 |  .6 |  .2 |  .3 |  .9 |
  4 |  .4 |  .3 |  .3 |  .5 |

TABLE 2

第二个 table 是事件列表及其坐标:

create table dm_values 
(vx float,
vz float,
v float)

insert into dm_values (vx, vz) values (1 + rand()*3, 1 + rand()*3)
...
insert into dm_values (vx, vz) values (1 + rand()*3, 1 + rand()*3)

所以条目有坐标,但没有事件值

   vx  |  vz  |   v   |
-----------------------
  1.3  |  2.7 |  null |
  2.6  |  2.7 |  null |
  1.3  |  3.3 |  null |
  1.9  |  1.1 |  null |
  3.0  |  2.9 |  null |
  ...  |  ... |   ... |

任务

我想用与第一个最接近的值更新第二个 table。因此,对于第一个条目 (x = 1.3, z = 2.7),我希望将值更新为查找矩阵中 x = 1 和 z = 3 (.6) 的值。更新后的 table 将如下所示:

   vx  |  vz  |   v   |
-----------------------
  1.3  |  2.7 |   0.6 |
  2.6  |  2.7 |   0.3 |
  1.3  |  3.3 |   0.6 |
  1.9  |  1.1 |   0.7 |
  3.0  |  2.9 |   0.3 |
  ...  |  ... |   ... |

问题

理论上,我可以使用游标。但是我的 TABLE 1 有大约 2000 行 (~50x40) 而我的 TABLE 2 行只有几百万。游标方法需要数天、数周或数月才能完成。我需要一个性能更好的解决方案,非常感谢任何提示。

据我所知,您应该能够使用 JOIN 执行简单的 UPDATE,其中 ROUND vxvz 对于 JOIN 条件,性能方面,你必须在你的数据集上测试它。

这是 JOIN 数据的基本方法,注意我已经填充了 INSERT 脚本以获得完整的矩阵:

CREATE TABLE #dm_matrix
    (
      x FLOAT ,
      z FLOAT ,
      avgValue DECIMAL(2, 1)
    )


INSERT  INTO #dm_matrix
VALUES  ( 1, 1, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 1, 2, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 1, 3, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 1, 4, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 2, 1, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 2, 2, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 2, 3, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 2, 4, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 3, 1, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 3, 2, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 3, 3, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 3, 4, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 4, 1, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 4, 2, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 4, 3, RAND() )
INSERT  INTO #dm_matrix
VALUES  ( 4, 4, RAND() )

SELECT  *
FROM    #dm_matrix

CREATE TABLE #dm_values
    (
      vx DECIMAL(2, 1) ,
      vz DECIMAL(2, 1) ,
      v FLOAT
    )

INSERT  INTO #dm_values
        ( vx, vz )
VALUES  ( 1 + RAND() * 3, 1 + RAND() * 3 )
INSERT  INTO #dm_values
        ( vx, vz )
VALUES  ( 1 + RAND() * 3, 1 + RAND() * 3 )

SELECT  *
FROM    #dm_values

-- replace this SELECT with the UPDATE commands below to update values
SELECT  v.vx ,
        v.vz ,
        m.avgValue
FROM    #dm_values v
        INNER JOIN #dm_matrix m ON ROUND(v.vx, 0) = m.x
                                   AND ROUND(v.vz, 0) = m.z

DROP TABLE #dm_matrix
DROP TABLE #dm_values

对于 UPDATE 你会做这样的事情:

UPDATE v
SET v.v = m.avgValue
FROM #dm_values v 
INNER JOIN #dm_matrix m ON ROUND(v.vx, 0) = m.x AND ROUND(v.vz, 0) = m.z

SELECT * FROM #dm_values

产生:

矩阵:

x   z   avgValue
1   1   0.6
1   2   0.9  -- row 2 below
1   3   0.4
1   4   0.5
2   1   0.7
2   2   0.4
2   3   0.5  -- row 1 below
2   4   0.5
3   1   0.4
3   2   0.1
3   3   0.3
3   4   0.8
4   1   0.1
4   2   1.0
4   3   0.5
4   4   0.5  

值:

vx  vz  v
1.8 2.8 NULL  -- x = 2, z = 3
1.3 1.5 NULL  -- x = 1, z = 2

更新后:

vx  vz  v
1.8 2.8 0.5
1.3 1.5 0.9

注意:

为了post,我已经将数据类型更改为DECIMAL(2, 1),因此您可能需要根据您的实际数据集进行修改。

我认为您应该为此使用 cross apply 或相关子查询。

update t2
    set v = m.avgvalue
    from t2 cross apply
         (select top 1 m.*
          from dm_matrix
          order by square(m.x - t2.vx) + square(m.z - t2.vz)
         );

我不确定你对距离使用的是什么函数,但欧氏距离似乎是一个合理的解释。