删除重复的行但保留首选行

时间:2015-03-17 00:30:56

标签: sql sqlite

我有一个简单的数据库表

create table demo (
  id     integer PRIMARY KEY,
  fv     integer,
  sv     text,
  rel_id integer,
  FOREIGN KEY (rel_id)
  REFERENCES demo(id));

我希望删除按fvsv分组的所有重复行。这已经是一个fairly popular question,有很好的答案。 但我需要扭曲这种情况。在rel_idNULL的情况下,我希望保留该行。任何其他情况都可以。

所以使用以下值

insert into demo (id,fv,sv,rel_id)
VALUES (1,1,'somestring',NULL),
       (2,2,'somemorestring',1),
       (3,1,'anotherstring',NULL),
       (4,2,'somemorestring',3),
       (5,1,'somestring',3)

无论

id | fv |     sv           | rel_id
---+----+------------------+-------
 1 | 1  | 'somestring'     | NULL
 2 | 2  | 'somemorestring' | 1
 3 | 1  | 'anotherstring'  | NULL

id | fv |     sv           | rel_id
---+----+------------------+-------
 1 | 1  | 'somestring'     | NULL
 3 | 1  | 'anotherstring'  | NULL
 4 | 2  | 'somemorestring' | 3

将是有效的结果。

id | fv |     sv           | rel_id
---+----+------------------+-------
 3 | 1  | 'anotherstring'  | NULL
 4 | 2  | 'somemorestring' | 3
 5 | 1  | 'somestring'     | 3

不会。由于第一个条目NULLrel_id,其总统职位高于NOT NULL

我目前有这个(这是基本重复问题的答案)作为删除重复项的查询,但我不知道如何继续修改查询以满足我的需求。

DELETE FROM demo
WHERE  id NOT IN (SELECT min(id) as id
                  FROM demo
                  GROUP BY fv,sv)

只要NOT NULL条目在NULL条目之前插入数据库,NOT NULL条目就不会被删除。保证rel_id始终指向rel_idNULL的条目,因此不存在删除引用条目的危险。此外,保证在rel_id IS NULL的同一组中不会有两行。因此,rel_id IS NULL行对整个表来说都是唯一的。

或作为基本算法:

  1. 浏览所有行,并按fvsv
  2. 对其进行分组
  3. 查看每个组中rel_id IS NULL行。如果有保留该行(并删除其余行)。否则选择一行,然后删除其余部分。
  4. sqlfiddle

1 个答案:

答案 0 :(得分:0)

我好像已经解决了

DELETE FROM demo
    WHERE  id NOT IN (SELECT min(id) as id
                      FROM demo AS out_buff
                      WHERE rel_id IS NULL OR
                            NOT EXISTS (SELECT id FROM demo AS in_buff
                                        WHERE rel_id IS NULL AND
                                              in_buff.fv = out_buff.fv AND
                                              in_buff.sv = out_buff.sv)
                      GROUP BY fv,sv);

通过在内部SELECT中选择仅rel_id具有值NULL的行或在GROUP BY参数上匹配的所有行,通过使用反条件为rel_id IS NULL行的存在。但我的查询看起来真的无效。作为一个天真的假设会使运行时间至少为O(n^2)