在SQL中删除数据库元素时调整复合键

时间:2017-02-24 13:03:21

标签: sql sqlite

考虑下表T

------------------------------
| CountryID | Obs    | Event |
------------------------------
| 1         | 1      | 10    |        
| 1         | 2      | 20    |
| 1         | 3      | 30    |
| 2         | 1      | 20    |
| 2         | 2      | 30    |
| 2         | 3      | 10    |
| 3         | 1      | 30    |
| 3         | 2      | 10    |
| 3         | 3      | 20    |
------------------------------

我想删除Event = 20所有的行,但是我想更新Obs,以便它们从1开始按增量顺序排列,差异为1.

例如,如果我运行SELECT * FROM T WHERE Event != 20,我会得到

------------------------------
| CountryID | Obs    | Event |
------------------------------
| 1         | 1      | 10    |        
| 1         | 3      | 30    |
| 2         | 2      | 30    |
| 2         | 3      | 10    |
| 3         | 1      | 30    |
| 3         | 2      | 10    |
------------------------------

但我想要

------------------------------
| CountryID | Obs    | Event |
------------------------------
| 1         | 1      | 10    |        
| 1         | 2      | 30    |
| 2         | 1      | 30    |
| 2         | 2      | 10    |
| 3         | 1      | 30    |
| 3         | 2      | 10    |
------------------------------

我需要什么查询来实现这一目标?

1 个答案:

答案 0 :(得分:0)

首先,在SQLite中,有一个名为rowid的伪列,它唯一地标识每一行。您可以使用相关子查询来执行您想要的操作:

update t
    set obs = (select count(*)
               from t t2
               where t2.countryid = t.countryid and t2.rowid <= t.rowid
              );

尽管如此,这是非常低效的,不应该在婴儿桌以外的任何其他地方运行。如果这是您经常要执行的操作,您可能会考虑使用比SQLite更强大的数据库。