使用查找矩阵中最接近的值更新 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
vx
和 vz
对于 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)
);
我不确定你对距离使用的是什么函数,但欧氏距离似乎是一个合理的解释。
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
vx
和 vz
对于 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)
);
我不确定你对距离使用的是什么函数,但欧氏距离似乎是一个合理的解释。