我正在制作一个系统,其中有一个同时发生的情况,例如假设用户 1 单击用户 2 的按钮并且两个用户的名称都保存在数据库中,并且如果用户 2 也单击用户 1 按钮(其中用户 2 是同一个用户用户 1 点击,在第二种情况下,用户 1 与在第一种情况下点击用户 1 的用户相同)。那么如何过滤掉这两个互相给予动作的用户呢?
user 1 user 2 action
frank ron 1
ron frank 1
这样它就表明存在巧合,因为两者都相互采取行动
有几种方法可以做到这一点。
由于您没有提供任何 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”之间的名称。很难看出这些数据有正确的答案。
此查询为每个匹配对返回一行。
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
它创建原始表的两个真子集的并集。在每一行中,第一列“小于”第二列。这具有制造重复行的效果。重复的行意味着每个用户已经“操作”了另一个。GROUP BY 和 HAVING 子句消除了单向操作。