【问题标题】:Update rows based on range around values without changing rows that are not initially within range根据值周围的范围更新行,而不更改最初不在范围内的行
【发布时间】:2021-11-08 22:02:43
【问题描述】:

在本地 SQLite (vs 3.29.0) 数据库中,有一个包含 3 列的表(不包括 rowID)。两个包含值,一个包含类别。我想根据一个特定类别的值的范围来更新类别。 SET 的类别必须可能与确定范围的类别相同。

例子:

id Value Value2 Category
1 20 20 2
2 30 30 2
3 40 40 2
4 70 70 2
5 5 5 1
6 19 19 1
7 26 26 1
8 42 42 1
9 49 49 1
10 52 52 1
11 71 71 1
12 90 90 1
13 17 17 1

我希望将行更改为类别 2,基于 value 周围的 4 范围和 value2 周围的 2 范围。这应该只更改第 6、9 和 11 行:

id Value Value2 Category
1 20 20 2
2 30 30 2
3 40 40 2
4 70 70 2
5 5 5 1
6 19 19 2
7 26 26 1
8 42 42 2
9 49 49 1
10 52 52 1
11 71 71 2
12 90 90 1
13 17 17 1

我当前的SQL语句是:

UPDATE tablename
SET Category = 2
WHERE (Category != 2
  AND EXISTS (
        SELECT *
        FROM tablename t
        WHERE t.Category = 2
          AND tablename.Value BETWEEN t.Value - 4 AND t.Value + 4
          AND tablename.Value2 BETWEEN t.Value2 -2 AND t.Value2 +2)
          );

其中的结果是:

id Value Value2 Category
1 20 20 2
2 30 30 2
3 40 40 2
4 70 70 2
5 5 5 1
6 19 19 2
7 26 26 1
8 42 42 2
9 49 49 1
10 52 52 1
11 71 71 2
12 90 90 1
13 17 17 2

似乎正在发生的事情是,由于第 6 行更改为第 2 类,第 13 行现在位于第 2 类行的值范围内,因此也被分配为第 2 类。如何更改声明,以便 SET 仅应用于最初在范围内的值?

有关示例,请参阅demo

【问题讨论】:

  • 你的 SQLite 版本是什么?
  • 版本 3.29.0(现在也包含在正文中)。
  • 如果您可以升级到(至少)3.33.0,您可以使用我回答中的代码。
  • 我正在研究这是否可能,但怀疑不是。我在一个预先确定的环境(QGIS 3.16,带有 python 3.7,它有一个预安装的 sqlite3 版本)中,我不能简单地改变它,而不影响我的 QGIS 插件的最终用户(谁必须做一个手动安装新版本而不是准备使用插件 - 最终用户不一定精通计算机,所以我试图避免这种情况。
  • 检查我的第二个查询。

标签: sql sqlite sql-update


【解决方案1】:

如果您的 SQLite 版本是 3.33.0+,您可以使用类似连接的 UPDATE...FROM 语法在 UPDATE 语句中执行自连接:

UPDATE tablename AS t1
SET Category = t2.Category
FROM tablename AS t2 
WHERE t2.Category = 2
  AND t1.Category <> t2.Category
  AND t1.Value BETWEEN t2.Value - 4 AND t2.Value + 4
  AND t1.Value2 BETWEEN t2.Value2 - 2 AND t2.Value2 + 2;

对于以前版本的SQLite,首先创建一个临时表,其中包含Category = 2的表的所有行:

CREATE TEMPORARY TABLE t AS 
SELECT * FROM tablename WHERE Category = 2;

然后更新表格:

UPDATE tablename
SET Category = 2
WHERE Category <> 2
  AND EXISTS (
        SELECT 1
        FROM t
        WHERE tablename.Value BETWEEN t.Value - 4 AND t.Value + 4
          AND tablename.Value2 BETWEEN t.Value2 -2 AND t.Value2 + 2
      );

请参阅demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    相关资源
    最近更新 更多