0

我有一个表,它存储一组属性并使它们按顺序排列。有可能从表中删除其中一个属性(行),并且应该压缩位置序列。

例如,如果我最初有这些值集:

+----+--------+-----+
| id | name   | pos |
+----+--------+-----+
|  1 | one    |   1 |
|  2 | two    |   2 |
|  3 | three  |   3 |
|  4 | four   |   4 |
+----+--------+-----+

并且第二行被删除,所有后续行的位置都应该更新以缩小差距。结果应该是这样的:

+----+--------+-----+
| id | name   | pos |
+----+--------+-----+
|  1 | one    |   1 |
|  3 | three  |   2 |
|  4 | four   |   3 |
+----+--------+-----+

有没有办法在单个查询中进行此更新?我怎么能这样做?

PS:我很欣赏 SQLServer 和 Oracle 的例子,因为系统应该支持这两个引擎。谢谢!

更新:这样做的原因是允许用户随意修改位置,以及添加或删除新行。位置显示给用户,因此,这些位置应始终显示一致的序列(并且该序列必须存储,而不是按需生成)。

4

3 回答 3

4

不确定它是否有效,但使用 Oracle 我会尝试以下操作:

update my_table set pos = rownum;
于 2011-02-01T13:08:11.550 回答
0

这会起作用,但对于大型数据集可能不是最理想的:

SQL> UPDATE my_table t
  2     SET pos = (SELECT COUNT(*) FROM my_table WHERE id <= t.id);

3 rows updated

SQL> select * from my_table;

        ID NAME              POS
---------- ---------- ----------
         1 one                 1
         3 three               2
         4 four                3
于 2011-02-01T13:52:24.957 回答
0

您真的需要序列值是连续的,还是只需要能够显示连续值?最简单的方法是让实际序列变得稀疏并根据顺序计算排名:

select id, 
       name, 
       dense_rank() over (order by pos) as pos,
       pos as sparse_pos 
from my_table

(注意:这是一个特定于 Oracle 的查询)

如果您首先使位置稀疏,这甚至会使重新排序更容易,因为您可以使每个新位置位于两个现有位置之间。例如,如果你有一个这样的表:

+----+--------+-----+
| id | name   | pos |
+----+--------+-----+
|  1 | one    | 100 |
|  2 | two    | 200 |
|  3 | three  | 300 |
|  4 | four   | 400 |
+----+--------+-----+

当需要将 ID 4 移动到位置 2 时,您只需将位置更改为 150。


进一步说明:

使用上面的示例,用户最初会看到以下内容(因为您正在屏蔽该位置):

+----+--------+-----+
| id | name   | pos |
+----+--------+-----+
|  1 | one    |   1 |
|  2 | two    |   2 |
|  3 | three  |   3 |
|  4 | four   |   4 |
+----+--------+-----+

当用户通过您的界面指示需要将位置 4 中的记录移动到位置 2 时,您将 ID 4 的位置更新为 150,然后重新运行您的查询。用户看到这个:

+----+--------+-----+
| id | name   | pos |
+----+--------+-----+
|  1 | one    |   1 |
|  4 | four   |   2 |
|  2 | two    |   3 |
|  3 | three  |   4 |
+----+--------+-----+

这不起作用的唯一原因是用户直接在数据库中编辑数据。不过,即使在那种情况下,我也倾向于通过视图和触发器来使用这种解决方案。

于 2011-02-01T14:55:13.283 回答