从没有主键SQL的表中删除行

时间:2013-08-23 00:20:53

标签: sql sqlite

我试图从SQL中的表表中删除多行。问题是我无法弄清楚如何使用子查询的结果从该表中删除,因为该表中没有主键。表的结构如下:

Friend ( ID1, ID2 )

ID1的学生与ID2的学生是朋友。友谊是相互的,所以如果(123, 456)在朋友表中,那么(456, 123)也是如此。

Likes ( ID1, ID2 )

ID1的学生喜欢ID2的学生。喜欢某人不一定是相互的,所以如果在{Likes}表中(123, 456),则无法保证(456, 123)也存在。

(No primary key)

我想解决的问题是:

“如果两个学生A和B是朋友,而A喜欢B但反之亦然,请删除Likes元组。”

提前致谢。

5 个答案:

答案 0 :(得分:1)

在大多数SQL方言中,您可以这样做:

delete from likes
    where not exists (select 1 from likes l2 where l2.id1 = likes.id2 and l2.id2 = likes.id1) and
          exists (select 1 from friends f where f.id1 = likes.id1 and f.id2 = likes.id2);

这几乎是你的两个条件的直接翻译。

答案 1 :(得分:1)

要解决您的问题,请使用以下sql查询

delete from friend where (ID1,ID2)  not in
(Select f1.ID1,f1.ID2 from friend f1, friend f2 where f1.ID1 = f2.ID2 && f1.ID2 = f2.ID1)

如果您的数据库不支持“in”子句中的mulitple列,则使用以下查询

delete from friend where concat(ID1,':',ID2)  not in
(Select concat(f1.ID1,':',f1.ID2) from friend f1, friend f2 
where f1.ID1 = f2.ID2 && f1.ID2 = f2.ID1)

我们可以将ID1和ID2的组合视为复合主键吗?

最好始终在每个表中使用主键。 请使用整数自动增量字段将主键添加到表中,这将很容易解决您的问题

答案 2 :(得分:1)

非常有趣的问题: -

在这里我创建你的表并尝试创建相同的场景,我找到了解决方案。 愿它帮助你...

 CREATE TABLE friends
  (
     id1 NUMERIC,
     id2 NUMERIC
  );

CREATE TABLE likes
  (
     id1 NUMERIC,
     id2 NUMERIC
  );

INSERT INTO friends
VALUES      (1,
             2);

INSERT INTO friends
VALUES      (2,
             1);

INSERT INTO friends
VALUES      (1,
             3);

INSERT INTO friends
VALUES      (3,
             1);

INSERT INTO friends
VALUES      (3,
             2);

INSERT INTO friends
VALUES      (2,
             3);

INSERT INTO likes
VALUES      (1,
             2);

INSERT INTO likes
VALUES      (2,
             1);

INSERT INTO likes
VALUES      (1,
             3);

INSERT INTO likes
VALUES      (3,
             1);

INSERT INTO likes
VALUES      (2,
             3);

SELECT *
FROM   friends

SELECT *
FROM   likes

SELECT *
FROM   likes A
WHERE  NOT EXISTS (SELECT 1
                   FROM   likes B
                   WHERE  A.id1 = B.id2
                          AND A.id2 = B.id1
                          AND EXISTS (SELECT 1
                                      FROM   friends
                                      WHERE  A.id1 = friends.id1
                                             AND A.id2 = friends.id2));

您的删除查询将是......

 DELETE A
    FROM   likes AS A
    WHERE  NOT EXISTS (SELECT 1
                       FROM   likes B
                       WHERE  A.id1 = B.id2
                              AND A.id2 = B.id1
                              AND EXISTS (SELECT 1
                                          FROM   friends
                                          WHERE  A.id1 = friends.id1
                                                 AND A.id2 = friends.id2));  

答案 3 :(得分:0)

我试图为这个问题找到答案。它适用于我的小测试数据,但是请指出它对于更大的数据是否效率低,或者如何通过更好的解决方案使其更好。

Delete from Likes where
ID1 in (select Q.ID1
from (select x.ID1, x.ID2
from (select A.ID1,A.ID2,B.ID2 as se
from Likes A left join Likes B
on A.ID2=B.ID1) x where x.ID1 <> x.se or x.se is null) Q inner join Friend F
where Q.ID1 = F.ID1 and Q.ID2 = F.ID2 order by Q.ID1)

and ID2 in  (select Q.ID2
from (select x.ID1, x.ID2
from (select A.ID1,A.ID2,B.ID2 as se
from Likes A left join Likes B
on A.ID2=B.ID1) x where x.ID1 <> x.se or x.se is null) Q inner join Friend F
where Q.ID1 = F.ID1 and Q.ID2 = F.ID2 order by Q.ID1)

答案 4 :(得分:0)

通过连接将两列表示为一个值,然后使用反向组合的NOT IN ()

delete from likes
where id1 || ' ' || id2 not in (select id2 || ' ' || id1 from likes);

在SQLFiddle上查看live demo,显示此查询确实有效。