3

I am trying to delete several rows from a table table in SQL. The problem is that I can't figure out how to delete from that table using the result of a subquery, as there is no primary key in that table. The structure of the tables is as follows:

Friend ( ID1, ID2 )

The student with ID1 is friends with the student with ID2. Friendship is mutual, so if (123, 456) is in the Friend table, so is (456, 123).

Likes ( ID1, ID2 )

The student with ID1 likes the student with ID2. Liking someone is not necessarily mutual, so if (123, 456) is in the Likes table, there is no guarantee that (456, 123) is also present.

(No primary key)

The situation I am trying to solve is:

"If two students A and B are friends, and A likes B but not vice-versa, remove the Likes tuple."

Thanks in advance.

4

5 回答 5

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”子句中的多列,请使用以下查询

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 的组合视为复合主键吗?

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

于 2013-08-23T05:11:41.570 回答
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));  
于 2013-08-23T08:41:23.193 回答
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);

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

于 2013-08-23T00:38:31.823 回答
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)
于 2013-08-23T15:53:49.480 回答
0

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

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

查看 SQLFiddle 上的现场演示,显示此查询确实有效。

于 2013-08-23T16:15:53.173 回答