PostgreSQL:如何访问匿名记录上的列

Posted

技术标签:

【中文标题】PostgreSQL:如何访问匿名记录上的列【英文标题】:PostgreSQL: How to access column on anonymous record 【发布时间】:2014-12-06 01:34:15 【问题描述】:

我有一个正在处理的问题。下面是显示问题的简化查询:

WITH the_table AS (
    SELECT a, b 
    FROM (VALUES('data1', 2), ('data3', 4), ('data5', 6)) x (a, b)
), my_data AS (
    SELECT 'data7' AS c, array_agg(ROW(a, b)) AS d
    FROM the_table
)
SELECT c, d[array_upper(d, 1)]
FROM my_data

在我的数据部分,您会注意到我正在从多行创建一个数组,并且该数组与其他数据在一行中返回。该数组需要包含ab 的信息,并保持两个值链接在一起。似乎有意义的是使用匿名行或记录(我想避免实际创建复合类型)。

这一切都很好,直到我需要开始提取数据。在上面的例子中,我需要访问数组中的最后一个条目,这可以通过使用array_upper 轻松完成,但是我需要访问曾经是b 列中的值,我无法弄清楚怎么办。

基本上,现在上面的查询正在返回:

"data7";"(data5,6)"

我需要返回

"data7";6

我该怎么做?

注意:虽然在上面的示例中,我使用文本和整数作为数据的类型,但它们并不是实际的最终类型,而是用于简化示例。

注意:这是使用 PostgreSQL 9.2

编辑:为了澄清,像SELECT 'data7', 6 这样的东西不是我想要的。想象一下,the_table 实际上是从数据库表中提取的,而不是我为了方便而放入的 WITH 语句,而且我不知道表中有什么数据。

换句话说,我希望能够做这样的事情:

SELECT c, (d[array_upper(d, 1)]).b
FROM my_data

然后把它拿回来:

"data7";6

基本上,一旦我使用 row() 函数将某些内容放入匿名记录中,如何将其取回?如何拆分 'data5' 部分和 6 部分,使它们不会同时返回一列?

再举个例子:

SELECT ROW('data5', 6)

使 'data5' 和 6 在一列中返回。如何取那一列并将其拆分回原来的两列?

我希望澄清

【问题讨论】:

为什么需要使用数组来处理看似简单的聚合查询? 这是一个简化的例子,让我的问题更清楚。完整查询使用递归 with 语句来收集数据(包括带有数组的行),然后我在一个列上使用 DISTINCT ON 并在另一列上使用 ORDER BY 来消除递归查询生成的不需要的数据。例如,如果我只需要 a 列中的数据,但我需要 a 和 b,这一切都很好,而且我不能失去它们的关联。如果我使用的是 pgsql 9.4,那么我只需将 a 和 b 放在单独的数组中,然后使用它必须稍后重新关联 a 和 b 的多列 unnest。但我在 9.2。 可以在此处找到具有类似问题且在这种情况下不起作用的答案的页面:postgresql.org/message-id/… @TrevorYoung:你能发布真实的查询和一些真实的数据吗?读者就这样在黑暗中摸索。您的 OP 是关于数组中的行,您上面的评论是关于一行中的数组。到目前为止,您发布的内容具有相当简单的解决方案 SELECT 'data7', 6;,这显然不是您要寻找的... 下次我工作时必须拉出查询,但示例的重点是保持简单。我的问题很简单,就是如何从由 row() 函数创建的对象内部返回一列? 【参考方案1】:

如果可以安装hstore 扩展:

with the_table as (
    select a, b
    from (values('data1', 2), ('data3', 4), ('data5', 6)) x (a, b)
), my_data as (
    select 'data7' as c, array_agg(row(a, b)) as d
    from the_table
)
select c, (avals(hstore(d[array_upper(d, 1)])))[2]
from my_data
;
   c   | avals 
-------+-------
 data7 | 6

【讨论】:

这基本上正是我正在寻找的,除了你必须下载一个扩展才能使它工作。我不知道,我只是觉得你可以建造一个除非你使用扩展才能拆开的结构有点愚蠢。无论如何,我现在会给你一个赞成票,如果没有人提出更原生的解决方案(没有扩展),那么我会接受你的回答。 给你的问题。你知道 avals 方法是如何将两种不同的数据类型放入同一个数组中的吗?互联网上的大多数信息都说您不能拥有具有不同类型的数组,但 avals 似乎允许这样做。 等等,我在那里找到了我自己的问题的答案。它将所有内容都转换为文本并使用文本数组。它确实适用于我的文本和整数示例,但例如,使用复合类型可能会变得更加麻烦。如果可能的话,我更愿意找到能够维护类型的东西。【参考方案2】:

这只是围绕一个类似问题的快速汇总 - 不是您问题的答案。这似乎是识别列的一个方向。

with x as (select 1 a, 2  b union all values (1,2),(1,2),(1,2))
select a from x;

【讨论】:

以上是关于PostgreSQL:如何访问匿名记录上的列的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 查询的过滤条件中的列上的字符串操作如何影响它选择的计划

如何根据PostgreSQL中同一行的两个不同列更新具有唯一序列号的列?

如何访问使用 docker-compose 设置的 postgresql 数据库?

如果在单个请求中与 Oracle 和 PostgreSql 交互以处理超过 20 万条记录,如何提高 EF Core 性能

如何将“ALTER table [...] ADD column”之类的更改记录到我的 PostgreSQL 表中?

如何在 PostgreSQL、PL/pgSQL 上执行匿名代码块切换 CASE 语句?