SQL:如何查找相关项的集群?

时间:2014-03-08 13:08:01

标签: sql

我们有以下形式的架构:

CREATE TABLE p (
  id int(11) NOT NULL,
  PRIMARY KEY (id)
);

INSERT INTO p (id) VALUES (1), (2), (3), (4), (5), (6);

CREATE TABLE IF NOT EXISTS pi (
  product_id int(11) NOT NULL,
  value varchar(10) NOT NULL,
  PRIMARY KEY (product_id, value)
);

INSERT INTO pi (product_id, value) VALUES
(1, 'a'),
(1, 'b'),
(2, 'a'),
(3, 'b'),
(4, 'c'),
(5, 'd'),
(5, 'e'),
(6, 'd');
(6, 'e');

产品可以有多个标识符。

我们希望创建共享相同标识符的产品群集。例如:

Product 1
  ID a
  ID b

Product 2
  ID a

Product 3
  ID b

虽然产品2和3似乎无关,但通过检查产品1,我们发现所有三种产品都属于彼此,因为它们属于同一标识符组。

结果应该是断开的产品集群,其中每个产品只属于一个组。对于上面的示例数据,我想获得以下产品集群:

1, 2, 3
4
5, 6

有没有办法在纯SQL中实现这一点?

我们尚未确定引擎,因此任何开源SQL数据库方言都是可以接受的。

1 个答案:

答案 0 :(得分:0)

这主要是为了好玩,只有一个级别的集群。它适用于提供的样本数据,可能不是您的真实数据。表现可能也不好。假设PostgreSQL。

select
array_agg(gp.product_id)
from (
  select
  productat_id,
  array_agg(value)
  from pi
  group by product_id
) as gp
left join (
  select
  product_id,
  array_agg(value)
  from pi
  group by product_id
  having count(*)>1
) gp2
on gp.array_agg && gp2.array_agg 
and gp.product_id <> gp2.product_id
group by coalesce(gp2.array_agg, gp.array_agg);

 array_agg 
-----------
 {1,3,2}
 {5,6}
 {4}
(3 rows)