Sqlite 更新列

Sqlite Update columns

我的 table 中有 5 列:id、x、y、来源、距离。

对于每个 id,我想找到最近的 x 和 y 值并更新距离字段中的该值及其在源中的 id。

我可以使用以下查询更新距离:

UPDATE item SET distance = ( SELECT MIN( ABS (a.x - item.x) + ABS (a.y - item.y) ) 
FROM item AS a WHERE a.id != item.id )

但是我无法更新源代码,因为 sqlite 不支持单个 select 的多列更新。

当我尝试将查询放入 where 条件时,出现错误,没有 item.x

这样的列
UPDATE item SET link = ( SELECT id FROM item AS a WHERE a.id != item.id 
ORDER BY ABS (a.x - item.x) + ABS (a.y - item.y) LIMIT 1 )

如何解决我的查询?

首先,您可以使用如下逻辑为每条记录获取最接近的 ID:

select i.*,
       (select id
        from item i2
        where i2.id <> i.id
        order by abs(i2.x - i.x) + abs(i2.y - i.y)
       ) as closest_id
from item i;

您可以将其放入 with 子句中以简化查询的其余部分:

with closest as (
      select i.*,
             (select id
              from item i2
              where i2.id <> i.id
              order by abs(i2.x - i.x) + abs(i2.y - i.y)
             ) as closest_id
      from item i
     )
update item
    set link = (select closest_id from closest where closest.id = item.id),
        distance = (select abs(i2.x - c.x) + abs(i2.y - c.y)
                    from closest c join
                         item i2
                         on c.closest_id = i2.id
                    where closest.id = item.id
                   );

编辑:

如果 with 不可用,您可以在没有 with 的情况下执行此操作,只需多次使用子查询即可。但是,我建议进行两个更新:

update item
    set link = (select id
                from item i2
                where i2.id <> item.id
                order by abs(i2.x - item.x) + abs(i2.y - item.y)
               );

update item
    set distance = (select abs(i2.x - item.x) + abs(i2.y - item.y) 
                    from item i2
                    where i2.id = item.link
                   );

显然,SQLite 不允许在 ORDER BY 子句中引用外部 table。

您可以通过将距离计算添加到 SELECT 子句来解决此问题。这需要将另一个子查询围绕此包装到 return 只有一列:

 UPDATE item
 SET link = ( SELECT id
              FROM ( SELECT id,
                            ABS (a.x - item.x) + ABS (a.y - item.y)
                     FROM item AS a
                     WHERE a.id != item.id
                     ORDER BY 2
                     LIMIT 1 ))

如果先更新 link 列,则可以使用该值计算距离,而无需再次搜索整个 table:

UPDATE item
SET distance = ( SELECT ABS (a.x - item.x) + ABS (a.y - item.y)
                 FROM item AS a
                 WHERE a.id = item.link )