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 )
我的 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 )