それにはいくつかの方法があります。
SQL DDL が提供されていないので、いくつか追加します。(将来的には DDL を含めます。より多くの回答が得られるでしょう。)
create table test (
user_1 varchar(15) not null,
user_2 varchar(15) not null,
action integer not null,
primary key (user_1, user_2, action)
);
insert into test values
('frank', 'ron', 1),
('ron', 'frank', 1 );
-- This is a one-way action. It should be excluded from the results.
insert into test values
('ron', 'fred', 1);
insert into test values
('ron', 'fred', 2),
('fred', 'ron', 2);
これにより、一致ごとに行のペアが返されます。ペアは直接並べ替えられないため、このクエリを表現するのに特に適した方法ではありません。
select t1.user_1, t1.user_2, t1.action
from test t1
inner join test t2
on t2.user_1 = t1.user_2
and t2.user_2 = t1.user_1
and t2.action = t1.action
USER_1 USER_2 ACTION
--
frank ron 1
fred ron 2
ron frank 1
ron fred 2
その結果セットをソートしようとすると、'frank' と 'ron' の間に多くの名前が表示される可能性があります。このデータが正しい答えを持っているかどうかを確認するのは困難です。
このクエリは、一致したペアごとに 1 つの行を返します。
select user_1, user_2, action
from test
where user_1 < user_2
union all
select user_2, user_1, action
from test
where user_2 < user_1
group by user_1, user_2, action
having count(action) = 2
USER_1 USER_2 ACTION
frank ron 1
fred ron 2
元のテーブルの 2 つの適切なサブセットの和集合を作成します。各行で、最初の列は 2 番目の列よりも "小さい" です。これには、重複する行を作成する効果があります。重複する行は、各ユーザーが他のユーザーに対して「アクション」を実行したことを意味します。GROUP BY 句と HAVING 句は、一方向のアクションを排除します。