如何在SQL中查找指定数值列中值相似的行聚类?
基于差值阈值的SQL行聚类查询
测试数据
创建测试表并插入数据的命令:
sqlite3 tmp.sqlite "create table t (id integer, val integer)" sqlite3 tmp.sqlite <<EOF insert into t values (0, 0), (1, 5), (2, 10), (3, 14), (4, 15), (5, 16), (6, 20), (7, 25), (8, 29), (9, 30), (10, 30), (11, 31), (12, 35), (13, 40) EOF
核心参数
diff:两行val值的最大允许差值,满足该条件的行视为相邻行min_neighbours:将一组行判定为聚类所需的最小相邻行数量(包含自身)
示例说明
给定参数:
diff:1min_neighbours:2
期望输出
| id | val | n_neighbours |
|---|---|---|
| 3 | 14 | 2 |
| 4 | 15 | 3 |
| 5 | 16 | 2 |
| 8 | 29 | 3 |
| 9 | 30 | 4 |
| 10 | 30 | 4 |
| 11 | 31 | 3 |
全量计算结果
所有行的相邻行数量统计:
| id | val | n_neighbours |
|---|---|---|
| 0 | 0 | 1 |
| 1 | 5 | 1 |
| 2 | 10 | 1 |
| 3 | 14 | 2 |
| 4 | 15 | 3 |
| 5 | 16 | 2 |
| 6 | 20 | 1 |
| 7 | 25 | 1 |
| 8 | 29 | 3 |
| 9 | 30 | 4 |
| 10 | 30 | 4 |
| 11 | 31 | 3 |
| 12 | 35 | 1 |
| 13 | 40 | 1 |
计算逻辑示例
- 行0:
val范围为0-1到0+1(即-1到1),除自身外无其他行满足条件,故相邻行数量为1 - 行3:
val范围为13到15,除自身外仅行4(val=15)满足,故相邻行数量为2 - 行4:
val范围为14到16,除自身外有行3(val=14)和行5(val=16)满足,故相邻行数量为3
解决方案SQL语句
以下SQL语句可实现需求,通过自连接统计符合差值条件的行数,并筛选出满足最小相邻数要求的行:
SELECT t1.id, t1.val, COUNT(t2.id) AS n_neighbours FROM t t1 JOIN t t2 ON ABS(t1.val - t2.val) <= :diff GROUP BY t1.id, t1.val HAVING COUNT(t2.id) >= :min_neighbours ORDER BY t1.id;
使用时将:diff和:min_neighbours替换为实际参数值,比如示例中的1和2。
同类问题对比
已有类似问题要么未涉及整数范围判定,要么未明确“相似行”的定义:
- SQL Server:查找表中列值相似的行
- SQL:获取列值相似的行
- MySQL:查找列值重复/相似的行
- SQL:查找某列值相似的行
内容的提问来源于stack exchange,提问作者Ciro Santilli OurBigBook.com
相关产品推荐
相关产品推荐

