使用Postgresql查找值集群

时间:2016-12-20 12:20:20

标签: postgresql

考虑以下示例表:

CREATE TABLE rndtbl AS
SELECT
  generate_series(1, 10) AS id,
  random() AS val;

我希望找到每个id一个cluster_id,这样群集之间的距离至少为0.1。我该如何计算这样的集群分配?

一个具体的例子是:

select * from rndtbl ;
 id |        val
----+-------------------
  1 | 0.485714662820101
  2 | 0.185201027430594
  3 | 0.368477711919695
  4 | 0.687312887981534
  5 | 0.978742253035307
  6 | 0.961830694694072
  7 |  0.10397826647386
  8 | 0.644958863966167
  9 | 0.912827260326594
 10 | 0.196085536852479
(10 rows)

结果将是:集群中的id s(2,7,10)和另一个集群中的(5,6,9)和另一个集群中的(4,8),以及(1)和(1) 3)作为单身集群。

1 个答案:

答案 0 :(得分:3)

SELECT * FROM rndtbl ;
┌────┬────────────────────┐
│ id │        val         │
├────┼────────────────────┤
│  1 │  0.153776332736015 │
│  2 │  0.572575284633785 │
│  3 │  0.998213059268892 │
│  4 │  0.654628816060722 │
│  5 │  0.692200613208115 │
│  6 │  0.572836415842175 │
│  7 │ 0.0788379465229809 │
│  8 │  0.390280921943486 │
│  9 │  0.611408909317106 │
│ 10 │  0.555164183024317 │
└────┴────────────────────┘
(10 rows)

使用LAG窗口函数来了解当前行是否在新群集中:

SELECT *, val - LAG(val) OVER (ORDER BY val) > 0.1 AS new_cluster
FROM rndtbl ;
┌────┬────────────────────┬─────────────┐
│ id │        val         │ new_cluster │
├────┼────────────────────┼─────────────┤
│  7 │ 0.0788379465229809 │ (null)      │
│  1 │  0.153776332736015 │ f           │
│  8 │  0.390280921943486 │ t           │
│ 10 │  0.555164183024317 │ t           │
│  2 │  0.572575284633785 │ f           │
│  6 │  0.572836415842175 │ f           │
│  9 │  0.611408909317106 │ f           │
│  4 │  0.654628816060722 │ f           │
│  5 │  0.692200613208115 │ f           │
│  3 │  0.998213059268892 │ t           │
└────┴────────────────────┴─────────────┘
(10 rows)

最后,你可以SUM true的数量(仍由val排序)来获取行的集群(从0开始计算):

SELECT *, SUM(COALESCE(new_cluster::int, 0)) OVER (ORDER BY val) AS nb_cluster
FROM (
  SELECT *, val - LAG(val) OVER (ORDER BY val) > 0.1 AS new_cluster 
  FROM rndtbl 
) t
;
┌────┬────────────────────┬─────────────┬────────────┐
│ id │        val         │ new_cluster │ nb_cluster │
├────┼────────────────────┼─────────────┼────────────┤
│  7 │ 0.0788379465229809 │ (null)      │          0 │
│  1 │  0.153776332736015 │ f           │          0 │
│  8 │  0.390280921943486 │ t           │          1 │
│ 10 │  0.555164183024317 │ t           │          2 │
│  2 │  0.572575284633785 │ f           │          2 │
│  6 │  0.572836415842175 │ f           │          2 │
│  9 │  0.611408909317106 │ f           │          2 │
│  4 │  0.654628816060722 │ f           │          2 │
│  5 │  0.692200613208115 │ f           │          2 │
│  3 │  0.998213059268892 │ t           │          3 │
└────┴────────────────────┴─────────────┴────────────┘
(10 rows)