从自我加入

时间:2015-11-20 00:57:43

标签: sql oracle graph

我尝试从用户表和他们购买的相关产品创建一个非定向边列表。为此,我基于产品在桌面上进行自我加入,以便捕获通过他们购买相同产品的事实而连接的用户。我下面的查询的问题是,当我只想要其中一个时,它返回两个彼此相反的记录。如何实现这一目标?我试着弄乱一些分析函数,并且能够得到我想要的结果,但我想知道是否有更好的方法,因为这将在约6.5亿条记录上运行。

SQL Fiddle

create table user_products as (
  select 'user1' usr, 'bananas' products from dual
  union
  select 'user2', 'bananas' from dual
  union
  select 'user3', 'pickles' from dual
  );

select t1.usr, t2.usr 
from user_products t1
inner join user_products t2
  on t1.products = t2.products
where t1.usr != t2.usr;

查询结果:

|   USR |   USR |
|-------|-------|
| user2 | user1 |
| user1 | user2 |

期望的结果:

|   USR |   USR |
|-------|-------|
| user1 | user2 |

通过last_value函数工作,但想知道是否有更好的方法?

select * from (
select usr userA, last_value(usr ignore nulls) over(partition by products order by products
rows between unbounded preceding and 1 preceding) userB from user_products)
where userB is not null;

查询结果:

| USERA | USERB |
|-------|-------|
| user2 | user1 |

1 个答案:

答案 0 :(得分:4)

只需在<条件中使用>join,而不是!=

select t1.usr, t2.usr 
from user_products t1
inner join user_products t2
  on t1.products = t2.products
where t1.usr < t2.usr;