我有一个数组作为一列的表,我想将数组元素加在一起:
> create table regres(a int[] not null);
> insert into regres values ('{1,2,3}'), ('{9, 12, 13}');
> select * from regres;
a
-----------
{1,2,3}
{9,12,13}
Run Code Online (Sandbox Code Playgroud)
我希望结果如下:
{10, 14, 16}
Run Code Online (Sandbox Code Playgroud)
那就是:{1 + 9, 2 + 12, 3 + 13}.
这样的功能在某处已经存在吗?插入扩展看起来是一个很好的候选者,但这样的功能尚不存在.
预计数组的长度在24到31个元素之间,所有元素都是NOT NULL,并且数组本身也将是NOT NULL.所有元素都是基本的int.每个聚合将有两行以上.在查询中,所有数组都将具有相同数量的元素.不同的查询将具有不同数量的元素.
我的实现目标是:x86_64-unknown-linux-gnu上的PostgreSQL 9.1.13,由gcc编译(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3,64位
PostgreSQL可以在任何地方开始使用数组下标.
考虑这个创建一个包含3个元素的数组的示例,其中包含5到7的下标:
SELECT ('[5:7]={1,2,3}'::int[]);
Run Code Online (Sandbox Code Playgroud)
返回:
[5:7]={1,2,3}
Run Code Online (Sandbox Code Playgroud)
例如,你得到第一个元素的含义
SELECT ('[5:7]={1,2,3}'::int[])[5];
Run Code Online (Sandbox Code Playgroud)
我想规范化 任何给定的1维数组以从数组下标1开始.
我能想到的最好的:
SELECT ('[5:7]={1,2,3}'::int[])[array_lower('[5:7]={1,2,3}'::int[], 1):array_upper('[5:7]={1,2,3}'::int[], 1)]
Run Code Online (Sandbox Code Playgroud)
或者,同样,更容易阅读:
WITH x(a) AS (
SELECT '[5:7]={1,2,3}'::int[]
)
SELECT a[array_lower(a, 1):array_upper(a, 1)]
FROM x
Run Code Online (Sandbox Code Playgroud)
你知道更简单/更快或更优雅的方式吗?
为了测试性能,我提出了这个快速基准测试.
表有100k行,随机长度在1和11之间的简单整数数组:
CREATE TEMP TABLE t (a int[]);
INSERT INTO t -- now with actually varying subscripts
SELECT ('[' || g%10 || ':' || 2*(g%10) || ']={1'
|| repeat(','||g::text, g%10) || '}')::int[]
FROM generate_series(1,100000) g;
EXPLAIN ANALYZE
SELECT
substring(a::text, '{.*$')::int[] -- Total runtime: 949.304 …Run Code Online (Sandbox Code Playgroud) 我们有一个遗留系统,试图跟踪特定文档保存的所有数据版本.我们最初将JSON作为字符串存储在一些旧版本的Postgres中,但最近我们升级到Postgres 9.3并且我们开始使用JSON列类型.
我们有一个名为"versions"的列,它有一个数组,每个保存的特定文档版本都存储在数组中,所以这样的查询:
SELECT _data_as_json FROM measurements WHERE id = 3307551
Run Code Online (Sandbox Code Playgroud)
像这样返回JSON:
{"reports": {}, "versions": [
{"timestamp": "2014-04-28T19:12:31.567415", "user": 11327, "legacy": {}, "vd_version": 1},
{"timestamp": "2014-05-12T18:03:24.417029", "user": 11331, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-05-12T21:52:50.045758", "user": 10373, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-05-14T23:34:37.797822", "user": 10380, "legacy": {"lengthmoment": {"moment": {"size": 130}, "length": {"in": 64.0}}, "comments": "", "custom": null}, "vd_version": 1},
{"timestamp": "2014-07-16T14:56:38.667363", …Run Code Online (Sandbox Code Playgroud) 如何在 PostgreSQL 中按字符分割字符串并在每个字符后添加新行
例如
num desc
1 Hello
2 Bye
num desc
1 H
e
l
l
o
2 B
y
e
Run Code Online (Sandbox Code Playgroud) 我有一个类似于以下的表:
CREATE TABLE stats (
name character varying(15),
q001001 numeric(9,0),
q001002 numeric(9,0),
q001003 numeric(9,0),
q001004 numeric(9,0),
q001005 numeric(9,0)
)
Run Code Online (Sandbox Code Playgroud)
我需要在这个表中查询各个字段的总和,如下所示:
SELECT sum(q001001) as total001,
sum(q001002) as total002,
sum(q001005) as total005,
FROM stats;
Run Code Online (Sandbox Code Playgroud)
这会产生一行数据和三列数据.
但是,出于报告目的,我需要以相反的方式列出结果.我需要三行和一列(好吧,实际上是两个,第一个是总和的字段),如下所示:
FieldName | SUM
----------+-------
q001001 | 12345
q001002 | 5432
q001005 | 986
Run Code Online (Sandbox Code Playgroud)
我想使用这样的一些SQL,其中field_name(来自stats表中字段名称的查找表)用于子查询:
select l.field_name, (select sum(l.field_name) from stats)
from stats_field_names_lookup as l
where l.field_name in ('Q001001', 'Q001002', 'Q001005');
Run Code Online (Sandbox Code Playgroud)
这里的想法是,sum(l.field_name)将替换为相关的实际字段名称,对于WHERE子句中的每个名称,然后进行评估以提供正确的求和结果值.但是,这会因以下错误而失败:
函数和(字符变化)不存在
因为值有文字/字符.如何将该字符值转换为要正确计算的未加引号的字符串?
这个SQL有效.但是,当然,每个都给出相同的和值field_name,因为它q001001在这里是硬编码的.
select l.field_name, …Run Code Online (Sandbox Code Playgroud) 我明白使用
SELECT unnest(ARRAY[5,3,9]) as id
Run Code Online (Sandbox Code Playgroud)
如果没有ORDER BY子句,则不保证结果集的顺序.我可以得到:
id
--
3
5
9
Run Code Online (Sandbox Code Playgroud)
但是以下请求呢:
SELECT
unnest(ARRAY[5,3,9]) as id,
unnest(ARRAY(select generate_series(1, array_length(ARRAY[5,3,9], 1)))) as idx
ORDER BY idx ASC
Run Code Online (Sandbox Code Playgroud)
是否保证2个unnest()调用(具有相同的长度)将并行展开,并且索引idx确实匹配数组中项目的位置?
我正在使用PostgreSQL 9.3.3.
sql postgresql unnest postgresql-9.3 set-returning-functions
我有同样的问题:
在Postgresql中拆分逗号分隔的字段并在所有结果表上执行UNION ALL
只是我的'fruits'列由'|'分隔.当我尝试:
SELECT
yourTable.ID,
regexp_split_to_table(yourTable.fruits, E'|') AS split_fruits
FROM yourTable
Run Code Online (Sandbox Code Playgroud)
我得到以下内容:
Run Code Online (Sandbox Code Playgroud)ERROR: type "e" does not exist
Q1.怎么E办?我看到一些E不使用的例子.官方文档没有在他们的"快速棕色狐狸......"中解释它.
Q2.我该如何使用'|' 作为我查询的分隔符?
编辑:我正在使用PostgreSQL 8.0.2.unfst()和regexp_split_to_table()都不受支持.
这是我(也许通常适合你)的非优化解决方案:
使用非优化内部函数的PG问题的解决方法:
CREATE FUNCTION unnest_with_idx(anyarray)
RETURNS TABLE(idx integer, val anyelement) AS
$$
SELECT generate_series(1,array_upper($1,1)) as idx, unnest($1) as val;
$$ LANGUAGE SQL IMMUTABLE;
Run Code Online (Sandbox Code Playgroud)
测试:
SELECT idx,val from unnest_with_idx(array[1,20,3,5]) as t;
Run Code Online (Sandbox Code Playgroud)
但是,正如我所说,非优化.我不敢相信(!!)PostgreSQL没有数组的内部索引......?但在这种情况下,问题是如何直接访问这个GIN类内部计数器的指数?
注1:上面的解决方案和问题与" 如何通过数组的每个元素创建索引? "不同.也可以与" Can PostgreSQL索引数组列? "不同,因为该函数用于隔离数组,而不是用于数组字段的表索引.
NOTE2(在答案后编辑):"数组索引"(更常用的术语)或"数组下标"或"数组计数器"是我们可以在语义路径中使用的术语,用于将"内部计数器",累加器引用到下一个数组项目.我看到没有PostgreSQL命令提供对此计数器的直接访问.作为generate_series()函数,generate_subscripts()函数是序列生成器,并且性能(最好但是)接近相同.通过其他手工row_number()功能提供了对"内部行计数器"的直接访问,但它是关于行,而不是关于数组,不幸的是性能更差.
我正在实现一个Query系统.我实现了不需要的功能.现在用户询问在单个select语句中使用多个unfst.我使用PostgreSQL作为指南,因为大多数用户在我们的查询系统之前使用它.
PostgreSQL有这样奇怪的行为:
postgres=# select unnest(array[1,2]), unnest(array[1,2]);
unnest | unnest
--------+--------
1 | 1
2 | 2
(2 rows)
postgres=# select unnest(array[1,2]), unnest(array[1,2,3]);
unnest | unnest
--------+--------
1 | 1
2 | 2
1 | 3
2 | 1
1 | 2
2 | 3
(6 rows)
Run Code Online (Sandbox Code Playgroud)
我的实现总是生成笛卡尔积.我想知道,这背后的正确逻辑是什么?PostgreSQL正在做正确的事还是只是一个bug?我没有在ANSI文档或PostgreSQL文档中找到明确的描述.
我有一个来自 json 对象的数组:[1, 9, 12]
由于它使用方括号表示法,因为它是直接从 json 对象获取的,所以我无法将其转换为,::integer[]当我尝试使用时,array_agg(jsonb_array_elements(simpleintarray))我收到一条错误消息,说我需要按 id 进行分组,但由于数组不是对象(键/值) )对,但只是简单的整数,我不知道如何以相当有效的方式实现这一点。
从 json 返回上述简单 int 数组的查询是:
SELECT node.*, elem->'permissions' AS group_node_permissions
FROM node
LEFT OUTER JOIN
jsonb_array_elements(my_user_group.node_permissions) elem
ON elem->>'id' = node.id::text
ORDER BY node.id
Run Code Online (Sandbox Code Playgroud)
elem->'permissions'理想情况下应该以 Postgres 数组的形式返回{},以便我稍后可以在其上使用该ANY(intarray)函数。
我想避免做多余的低效解决方法,例如用大括号替换方括号,然后转换elem->'permissions'为->>整数数组,将其转换为字符串,尽管这可能会起作用。
在伪代码中,我真正需要的是能够得到相同的结果:
SELECT node.*, elem->'permissions'**::integer[]** AS group_node_permissions,
...但是当然由于json 数组与 PostgreSQL 数组格式之间的[]差异{},这会导致错误。
这是我当前的(非常丑陋的解决方案,但有效):
SELECT node.*, replace(replace(elem->>'permissions', '[', '{'),']','}')::integer[] AS group_node_permissions
Run Code Online (Sandbox Code Playgroud)
它将原始的 (jsonb) 转换为(integer[])[1, 9, …
postgresql ×10
sql ×4
arrays ×3
json ×2
unnest ×2
dynamic-sql ×1
indexing ×1
performance ×1
types ×1
unpivot ×1