Maybe the following will be useful for you: create a new table, SELECT everything you need from the old table, and INSERT it into the new table. You could use a self/left join to see the "mutual" friendships side by side as it were (the "case ... when ... then" is only added to make this easier to see).
-- the "oldtable" contains your test data
select
O1.userid, O1.friendid
, O2.userid, O2.friendid
, case
when O1.userid = O2.friendid and O1.friendid = O2.userid then
concat( 'mutual -> ', O1.userid, O1.friendid )
else
' not mutual '
end friendship
from oldtable O1
left join oldtable O2
on O1.userid = O2.friendid and O1.friendid = O2.userid ;
-- output
userid friendid userid friendid friendship
2 1 1 2 mutual -> 21
1 2 2 1 mutual -> 12
3 1 1 3 mutual -> 31
1 3 3 1 mutual -> 13
4 2 2 4 mutual -> 42
2 4 4 2 mutual -> 24
1 4 4 1 mutual -> 14
4 1 1 4 mutual -> 41
1 5 null null not mutual
Let's create a new table.
create table newtable (
userid int
, friendid int
, confirmed int
, constraint ukey unique (userid, friendid) -- does not help much, but ..
);
The following queries are derived from the first one. For the duplicates, we pick one of each (the one with the lower userid), and insert them into the new table.
insert into newtable
select
O1.userid
, O1.friendid
, O1.confirmed
from oldtable O1
join oldtable O2
on O1.userid = O2.friendid and O1.friendid = O2.userid
where O1.userid < O2.userid ;
The "remaining" rows ie frienships without "duplicates" can be retrieved via a left join (and INSERTed into the new table).
insert into newtable
select
O1.userid
, O1.friendid
, O1.confirmed
from oldtable O1
left join oldtable O2
on O1.userid = O2.friendid and O1.friendid = O2.userid
where O2.userid is null
and O2.friendid is null;
Now, the new table contains:
mysql> select * from newtable;
+--------+----------+-----------+
| userid | friendid | confirmed |
+--------+----------+-----------+
| 1 | 2 | 1 |
| 1 | 3 | 1 |
| 2 | 4 | 1 |
| 1 | 4 | 1 |
| 1 | 5 | 0 |
+--------+----------+-----------+
5 rows in set (0.00 sec)
The query you have mentioned in your question returns the following rows:
select * from newtable where (userid=1 or friendid=1) and confirmed=1;
userid friendid confirmed
1 2 1
1 3 1
1 4 1
See dbfiddle here (also tested w/ MySQL 5.7)
Additional constraint
In order to prevent recording "duplicate friendships" in the future, I'd probably add a trigger that checks the existing records in the "newtable" before inserting. Something like ...
delimiter $
create trigger uniquefriendships before insert on newtable
for each row
begin
if exists (
select *
from newtable
where userid = new.friendid and friendid = new.userid
)
then
signal sqlstate '45000' set message_text = ' uniquefriendships trigger: friendship exists! ';
end if;
end$
delimiter ;
Testing:
-- okay
mysql> insert into newtable (userid, friendid) values (100,200) ;
Query OK, 1 row affected (0.00 sec)
-- fails due to unique constraint (duplicate)
mysql> insert into newtable (userid, friendid) values (100,200) ;
ERROR 1062 (23000): Duplicate entry '100-200' for key 'ukey'
-- fails due to trigger (friendship 100-200 exists)
mysql> insert into newtable (userid, friendid) values (200,100) ;
ERROR 1644 (45000): uniquefriendships trigger: friendship exists!