- 浏览: 302675 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
masuweng:
如何给新人机会 -
masuweng:
多sql结果集按列合并新结果报表实现方案 -
Ahe:
赞
坚持长跑方能赢 -
masuweng:
好好好
程序员如何更好的了解自己所做的事情 -
小楠人:
laoguan123 写道楼主好,使用过一些excel导入导出 ...
excell导入导出
PostgreSQL: 如何获取一维数组的相同元素并根据相似度排序
2011-11-02 22:24:09| 分类: Postgres基础 |举报|字号 订阅
今天开发有个需求,表中有一个列为一维数组类型,现在需要找出表中具有相同元素的数据,描述起来
可能有点费力,下面举个例子就明白了。
一 需求演示
--1.1测试表
mydb=> \d test_array;
Table "mydb.test_array"
Column | Type | Modifiers
--------+----------+-----------
id | integer |
phone | bigint[] |
mydb=> select * from test_array;
id | phone
----+-------------
1 | {1,2}
2 | {1,2,3}
3 | {2,3}
4 | {1,2,3,4}
5 | {1,2,3,4,5}
6 | {4,5,6}
备注: 给出一个 id, 然后找出与这个 id 对应的 phone 数组含有相同元素的记录,相同的元素越多,我们
就认为这两个元素越相似,并根据相似度降序排序。
--1.2 找出与 id=1 的 phone 数组含有相同的元素的记录
mydb=> select id,phone from test_array where phone && (select phone from test_array where id=1) and id!=1;
id | phone
----+-------------
2 | {1,2,3}
3 | {2,3}
4 | {1,2,3,4}
5 | {1,2,3,4,5}
备注:上面SQL虽然能成功找出具有相同元素的记录,但是不能根据相似度排序,今天总结了下,
有以下方法实现上面功能。
方法一:使用intarray模块比较 int4[] 的数组类型
--2.1 安装 intarray 模块
mydb=# create extension intarray;
CREATE EXTENSION
备注:intarray模块里有个 "&" 函数,可以找到数组元素的相同部分, 具体信息可查阅手册
http://www.postgresql.org/docs/9.1/static/intarray.html
--2.2 & 操作符使用
mydb=> select array[1,2,3] & array[1,2];
?column?
----------
{1,2}
(1 row)
--2.3 不支持 int8 类型的数组
mydb=> select array[11111111111,2,3] & array[11111111111,2];
ERROR: operator does not exist: bigint[] & bigint[]
LINE 1: select array[11111111111,2,3] & array[11111111111,2];
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
备注:intarray 模块虽然能比较并获得数组的相同元素,但仅支持 int4 数组类型。
--2.4 源码 & 操作符代码
CREATE OPERATOR & (
LEFTARG = _int4,
RIGHTARG = _int4,
COMMUTATOR = &,
PROCEDURE = _int_inter
);
备注:可以在 $PGHOME/share/extension 目录下查阅 intarray--1.0.sql 文件。
方法二:创建 intersection 函数,对 int8[] 数组类型进行比较
--3.1 create function
CREATE OR REPLACE FUNCTION intersection(anyarray, anyarray) RETURNS anyarray as $$
SELECT ARRAY(
SELECT $1[i]
FROM generate_series( array_lower($1, 1), array_upper($1, 1) ) i
WHERE ARRAY[$1[i]] && $2
);
$$ language sql;
备注:这里我们开发组的一名同事找到的,感谢这位同事。
--3.2 测试
mydb=> select intersection(array[11111111111,2,3],array[11111111111,2,3]);
intersection
-------------------
{11111111111,2,3}
(1 row)
备注:这次果然没报错了,这种方法虽然功能实现了,但效率如何呢?下面简单测试下。
四 性能测试
--4.1创建测试表并插入数据
mydb=> create table array_test (skyid serial primary key,phone_list int8[]);
NOTICE: CREATE TABLE will create implicit sequence "array_test_skyid_seq" for serial column "array_test.skyid"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "array_test_pkey" for table "array_test"
CREATE TABLE
mydb=> insert into array_test(phone_list) select regexp_split_to_array(id1||';'||id2||';'||id3||';'||id4,';')::int8[] from phone ;
INSERT 0 100000
mydb=> select * from array_test limit 10;
skyid | phone_list
-------+---------------
1 | {1,2,3,4}
2 | {2,3,4,5}
3 | {3,4,5,6}
4 | {4,5,6,7}
5 | {5,6,7,8}
6 | {6,7,8,9}
7 | {7,8,9,10}
8 | {8,9,10,11}
9 | {9,10,11,12}
10 | {10,11,12,13}
(10 rows)
--4.2 查询SQL
mydb=> select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=1 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> ;
skyid | phone_list | array_length
-------+------------+--------------
2 | {2,3,4,5} | 3
3 | {3,4,5,6} | 2
4 | {4,5,6,7} | 1
(3 rows)
--4.3 查看执行计划
mydb=> explain analyze select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=8 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> order by array_length(intersection(t1.phone_list,t2.phone_list),1) desc;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=3743.94..3745.19 rows=500 width=110) (actual time=1279.393..1279.423 rows=6 loops=1)
Sort Key: (array_length(intersection(t1.phone_list, t2.phone_list), 1))
Sort Method: quicksort Memory: 17kB
-> Nested Loop (cost=0.00..3721.53 rows=500 width=110) (actual time=0.651..1279.292 rows=6 loops=1)
Join Filter: ((t1.skyid <> t2.skyid) AND (t1.phone_list && t2.phone_list))
-> Index Scan using array_test_pkey on array_test t1 (cost=0.00..8.28 rows=1 width=57) (actual time=0.236..0.275 rows=1 loops=1)
Index Cond: (skyid =
-> Seq Scan on array_test t2 (cost=0.00..2087.00 rows=100000 width=57) (actual time=0.013..608.045 rows=100000 loops=1)
Total runtime: 1279.619 ms
(9 rows)
--4.4创建 gin 索引
mydb=> create index concurrently idx_array_test_phone_list on array_test using gin (phone_list);
CREATE INDEX
--4.5 再次查看PLAN
mydb=> explain analyze select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=7 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> order by array_length(intersection(t1.phone_list,t2.phone_list),1) desc;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=1070.18..1071.43 rows=500 width=110) (actual time=1.185..1.215 rows=6 loops=1)
Sort Key: (array_length(intersection(t1.phone_list, t2.phone_list), 1))
Sort Method: quicksort Memory: 17kB
-> Nested Loop (cost=19.88..1047.77 rows=500 width=110) (actual time=0.854..1.117 rows=6 loops=1)
Join Filter: (t1.skyid <> t2.skyid)
-> Index Scan using array_test_pkey on array_test t1 (cost=0.00..8.28 rows=1 width=57) (actual time=0.231..0.239 rows=1 loops=1)
Index Cond: (skyid = 7)
-> Bitmap Heap Scan on array_test t2 (cost=19.88..905.74 rows=500 width=57) (actual time=0.226..0.264 rows=7 loops=1)
Recheck Cond: (t1.phone_list && phone_list)
-> Bitmap Index Scan on idx_array_test_phone_list (cost=0.00..19.75 rows=500 width=0) (actual time=0.123..0.123 rows=7 loops=1)
Index Cond: (t1.phone_list && phone_list)
Total runtime: 1.399 ms
(12 rows)
备注:由于测试是在虚拟机上进行,数据量并不大,但从上面看出上面的SQL在创建了 gin 类型索引后,
执行时间在 1.3 毫秒左右,效率显著提高。
五 参考
http://blog.163.com/digoal@126/blog/static/163877040201192624726272/
http://www.itfingers.com/Question/756871/postgres-function-to-return-the-intersection-of-2-arrays/zh
http://www.postgresql.org/docs/9.1/static/intarray.html
http://www.postgresql.org/docs/9.1/static/indexes-types.html
2011-11-02 22:24:09| 分类: Postgres基础 |举报|字号 订阅
今天开发有个需求,表中有一个列为一维数组类型,现在需要找出表中具有相同元素的数据,描述起来
可能有点费力,下面举个例子就明白了。
一 需求演示
--1.1测试表
mydb=> \d test_array;
Table "mydb.test_array"
Column | Type | Modifiers
--------+----------+-----------
id | integer |
phone | bigint[] |
mydb=> select * from test_array;
id | phone
----+-------------
1 | {1,2}
2 | {1,2,3}
3 | {2,3}
4 | {1,2,3,4}
5 | {1,2,3,4,5}
6 | {4,5,6}
备注: 给出一个 id, 然后找出与这个 id 对应的 phone 数组含有相同元素的记录,相同的元素越多,我们
就认为这两个元素越相似,并根据相似度降序排序。
--1.2 找出与 id=1 的 phone 数组含有相同的元素的记录
mydb=> select id,phone from test_array where phone && (select phone from test_array where id=1) and id!=1;
id | phone
----+-------------
2 | {1,2,3}
3 | {2,3}
4 | {1,2,3,4}
5 | {1,2,3,4,5}
备注:上面SQL虽然能成功找出具有相同元素的记录,但是不能根据相似度排序,今天总结了下,
有以下方法实现上面功能。
方法一:使用intarray模块比较 int4[] 的数组类型
--2.1 安装 intarray 模块
mydb=# create extension intarray;
CREATE EXTENSION
备注:intarray模块里有个 "&" 函数,可以找到数组元素的相同部分, 具体信息可查阅手册
http://www.postgresql.org/docs/9.1/static/intarray.html
--2.2 & 操作符使用
mydb=> select array[1,2,3] & array[1,2];
?column?
----------
{1,2}
(1 row)
--2.3 不支持 int8 类型的数组
mydb=> select array[11111111111,2,3] & array[11111111111,2];
ERROR: operator does not exist: bigint[] & bigint[]
LINE 1: select array[11111111111,2,3] & array[11111111111,2];
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
备注:intarray 模块虽然能比较并获得数组的相同元素,但仅支持 int4 数组类型。
--2.4 源码 & 操作符代码
CREATE OPERATOR & (
LEFTARG = _int4,
RIGHTARG = _int4,
COMMUTATOR = &,
PROCEDURE = _int_inter
);
备注:可以在 $PGHOME/share/extension 目录下查阅 intarray--1.0.sql 文件。
方法二:创建 intersection 函数,对 int8[] 数组类型进行比较
--3.1 create function
CREATE OR REPLACE FUNCTION intersection(anyarray, anyarray) RETURNS anyarray as $$
SELECT ARRAY(
SELECT $1[i]
FROM generate_series( array_lower($1, 1), array_upper($1, 1) ) i
WHERE ARRAY[$1[i]] && $2
);
$$ language sql;
备注:这里我们开发组的一名同事找到的,感谢这位同事。
--3.2 测试
mydb=> select intersection(array[11111111111,2,3],array[11111111111,2,3]);
intersection
-------------------
{11111111111,2,3}
(1 row)
备注:这次果然没报错了,这种方法虽然功能实现了,但效率如何呢?下面简单测试下。
四 性能测试
--4.1创建测试表并插入数据
mydb=> create table array_test (skyid serial primary key,phone_list int8[]);
NOTICE: CREATE TABLE will create implicit sequence "array_test_skyid_seq" for serial column "array_test.skyid"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "array_test_pkey" for table "array_test"
CREATE TABLE
mydb=> insert into array_test(phone_list) select regexp_split_to_array(id1||';'||id2||';'||id3||';'||id4,';')::int8[] from phone ;
INSERT 0 100000
mydb=> select * from array_test limit 10;
skyid | phone_list
-------+---------------
1 | {1,2,3,4}
2 | {2,3,4,5}
3 | {3,4,5,6}
4 | {4,5,6,7}
5 | {5,6,7,8}
6 | {6,7,8,9}
7 | {7,8,9,10}
8 | {8,9,10,11}
9 | {9,10,11,12}
10 | {10,11,12,13}
(10 rows)
--4.2 查询SQL
mydb=> select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=1 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> ;
skyid | phone_list | array_length
-------+------------+--------------
2 | {2,3,4,5} | 3
3 | {3,4,5,6} | 2
4 | {4,5,6,7} | 1
(3 rows)
--4.3 查看执行计划
mydb=> explain analyze select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=8 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> order by array_length(intersection(t1.phone_list,t2.phone_list),1) desc;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=3743.94..3745.19 rows=500 width=110) (actual time=1279.393..1279.423 rows=6 loops=1)
Sort Key: (array_length(intersection(t1.phone_list, t2.phone_list), 1))
Sort Method: quicksort Memory: 17kB
-> Nested Loop (cost=0.00..3721.53 rows=500 width=110) (actual time=0.651..1279.292 rows=6 loops=1)
Join Filter: ((t1.skyid <> t2.skyid) AND (t1.phone_list && t2.phone_list))
-> Index Scan using array_test_pkey on array_test t1 (cost=0.00..8.28 rows=1 width=57) (actual time=0.236..0.275 rows=1 loops=1)
Index Cond: (skyid =
-> Seq Scan on array_test t2 (cost=0.00..2087.00 rows=100000 width=57) (actual time=0.013..608.045 rows=100000 loops=1)
Total runtime: 1279.619 ms
(9 rows)
--4.4创建 gin 索引
mydb=> create index concurrently idx_array_test_phone_list on array_test using gin (phone_list);
CREATE INDEX
--4.5 再次查看PLAN
mydb=> explain analyze select t2.skyid,t2.phone_list, array_length(intersection(t1.phone_list,t2.phone_list),1)
mydb-> from array_test t1, array_test t2
mydb-> where t1.skyid=7 and t1.skyid!=t2.skyid and t1.phone_list && t2.phone_list
mydb-> order by array_length(intersection(t1.phone_list,t2.phone_list),1) desc;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=1070.18..1071.43 rows=500 width=110) (actual time=1.185..1.215 rows=6 loops=1)
Sort Key: (array_length(intersection(t1.phone_list, t2.phone_list), 1))
Sort Method: quicksort Memory: 17kB
-> Nested Loop (cost=19.88..1047.77 rows=500 width=110) (actual time=0.854..1.117 rows=6 loops=1)
Join Filter: (t1.skyid <> t2.skyid)
-> Index Scan using array_test_pkey on array_test t1 (cost=0.00..8.28 rows=1 width=57) (actual time=0.231..0.239 rows=1 loops=1)
Index Cond: (skyid = 7)
-> Bitmap Heap Scan on array_test t2 (cost=19.88..905.74 rows=500 width=57) (actual time=0.226..0.264 rows=7 loops=1)
Recheck Cond: (t1.phone_list && phone_list)
-> Bitmap Index Scan on idx_array_test_phone_list (cost=0.00..19.75 rows=500 width=0) (actual time=0.123..0.123 rows=7 loops=1)
Index Cond: (t1.phone_list && phone_list)
Total runtime: 1.399 ms
(12 rows)
备注:由于测试是在虚拟机上进行,数据量并不大,但从上面看出上面的SQL在创建了 gin 类型索引后,
执行时间在 1.3 毫秒左右,效率显著提高。
五 参考
http://blog.163.com/digoal@126/blog/static/163877040201192624726272/
http://www.itfingers.com/Question/756871/postgres-function-to-return-the-intersection-of-2-arrays/zh
http://www.postgresql.org/docs/9.1/static/intarray.html
http://www.postgresql.org/docs/9.1/static/indexes-types.html
发表评论
-
PMP(Private Marketplace)
2015-11-06 17:06 656http://morketing.cn/special-col ... -
批量日志数据库外表写入
2015-06-15 17:15 685#创建外链表映射日志文件 audience_attribut ... -
网站回头客属性设置
2014-10-15 14:38 929人群分类实现: 每个客户可以自定义自己的目标人群计划。 一类是 ... -
关于异步操作的汇总
2014-09-29 13:06 1570随着互联网用户体验,和性能的要求,异步操作越来越凸显重要性。 ... -
SEM 自动化管理工具大起底(这其实是改写三个SEM优化问题的一部分)
2014-09-24 10:18 1276我们常说的 SEM 包含了 S ... -
在调用sql脚本时动态生成临时表处理
2014-09-18 16:52 657定义一张临时表,往里插数据,返回表名 temp_terms ... -
Hive 中内部表与外部表的区别与创建方法
2014-09-16 17:41 2595先来说下Hive中内部表与外部表的区别: Hive ... -
Hadoop的实时分析之路
2014-09-13 11:33 559随着大数据[注]时代 ... -
hadoop实时查询
2014-09-13 09:38 897Impala+Trevni 很有希望和 G ... -
用户行为属性分类的实现
2014-08-27 09:33 1025对于一个网站来说,分析用户属性,并标记属性标签对后续用户的潜在 ... -
pig将多对象按相同属性集合分组
2014-08-26 11:29 1093--对event和clicks分别取出分组字段,整体属性字 ... -
ruby接收pig流式处理文件内容
2014-08-26 10:58 1265大数据操作中涉及到数据清洗步奏还是用脚本处理比较方便,下边介绍 ... -
greenplum解决数组取交集问题
2014-08-25 23:13 1157最近要用到一个数组合并取交集的功能。 在网上查了一下postg ... -
PostgreSQL的ARRAY_AGG函数与unnest函数
2014-08-22 21:43 4731PostgreSQL的ARRAY_AGG函数是用来连接到一个数 ... -
pig过滤A表中有B表中无的数据实例
2014-08-20 18:27 1044--加载数据文件 events_raw_short = ... -
列式存储处理
2014-08-20 18:07 627下面以GBase 8a分析型数 ... -
列式存储处理
2014-08-20 18:04 524下面以GBase 8a分析型数据库为例,描述列存储对数据存储与 ... -
spark导读
2014-08-03 19:24 711类Hadoop的高效分布式计 ... -
Spark - 大数据Big Data处理框架
2014-08-03 08:32 581Spark - 大数据Big Data处理框架 (2014-0 ...
相关推荐
Maven坐标:org.postgresql:postgresql:42.3.1; 标签:postgresql、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构...
Maven坐标:org.postgresql:postgresql:42.2.5; 标签:postgresql、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和...
Bruce Momjian作为PostgreSQL的核心开发者之一,编写了《PostgreSQL:简介和概念》一书,旨在向数据库新手和有一定经验的开发者提供一本实用的指南。 该书内容覆盖了PostgreSQL的基本概念、架构设计、SQL语言使用、...
Maven坐标:org.postgresql:postgresql:42.2.2; 标签:postgresql、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和...
### PostgreSQL: Up and Running 关键知识点解析 #### 标题与描述分析 - **书籍名称**:“PostgreSQL: Up and Running”(2012年7月版),由Regina Obe和Leo Hsu共同撰写。 - **主要内容**:本书为读者提供了关于...
在提供的`JDBCTest`文件中,可能包含了上述示例的完整代码,你可以根据实际情况调整参数以连接到你的PostgreSQL数据库,并从指定的表中获取数据。通过学习和理解这个例子,你可以轻松地将JDBC技术应用到自己的Java...
postgresql-42.6.0.jar 对 java 8的支持postgresql驱动包
PostgreSQL社区于2020年10月17日发布JDBC紧急修复版本v42.2.18。该版本主要修复了42.2.17版本中并未完全修复的gssEncMode问题。
标题"POSTgreSQL:51风控系统背后的利器_"暗示了POSTgreSQL数据库在构建51风控系统中的核心作用。51风控系统可能是一个金融或互联网平台的风险控制系统,用于预防和管理潜在的欺诈行为。POSTgreSQL,作为一款开源的...
《PostgreSQL:介绍与概念》是一本全面介绍了PostgreSQL这一强大数据库系统的书籍,不仅适合初学者入门,也为有经验的数据库管理员提供了深入的技术指导。通过阅读本书,读者可以全面掌握PostgreSQL的各种功能,并...
这里,`items` 字段是一个二维数组,每个元素包含两个小数组,分别表示价格和数量。这样,我们就可以在一个字段中存储多个商品的记录。 #### 四、插入数据 为了向上述表中插入数据,可以使用以下SQL语句: ```sql...
PostgreSQL 是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。它提供了相对其他开放源代码数据库系统(比如 MySQL 和 Firebird),自从MySQL被Oracle收购以后,PotgreSQL逐渐成为...
工具连接postgresql需要的jar包
Maven坐标:org.postgresql:postgresql:42.2.2; 标签:postgresql、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构...
Chapter 7 SQL the PostgreSQL way Chapter 8 Writing Functions Chapter 9 Query Performance Tuning Chapter 10 Replication and External data Appendix A. Installing PostgreSQL Appendix B. PostgreSQL ...
1. pg13.4
一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: 一、服务器进程的启动和关闭: . 50 PostgreSQL PostgreSQL...