”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > PostgreSQL unnest()函数获取元素编号方法

PostgreSQL unnest()函数获取元素编号方法

发布于2025-04-13
浏览:668

How to Get the Element Number When Using PostgreSQL's unnest() Function?

PostgreSQL unnest() 函数与元素编号

问题

当遇到包含分隔值的列时,unnest() 函数提供了一种提取这些值的方法:

myTable
id | elements
--- ------------
1  |ab,cd,efg,hi
2  |jk,lm,no,pq
3  |rstuv,wxyz

select id, unnest(string_to_array(elements, ',')) AS elem
from myTable

id | elem
--- -----
1  | ab
1  | cd
1  | efg
1  | hi
2  | jk
...

但是,您可能希望也包含元素编号,格式如下:

id | elem | nr
--- ------ ---
1  | ab   | 1
1  | cd   | 2
1  | efg  | 3
1  | hi   | 4
2  | jk   | 1
...

最终目标是在不使用窗口函数(如 row_number()rank())的情况下获得源字符串中每个元素的原始位置,因为这些函数始终返回 1,这可能是因为所有元素都位于源表的同一行中。

解决方法

PostgreSQL 14 或更高版本

对于逗号分隔的字符串,请使用 string_to_table() 代替 unnest(string_to_array())

SELECT t.id, a.elem, a.nr
FROM   tbl t
LEFT   JOIN LATERAL string_to_table(t.elements, ',') WITH ORDINALITY AS a(elem, nr) ON true

演示

PostgreSQL 9.4 或更高版本

对于返回集合的函数,使用 WITH ORDINALITY

SELECT t.id, a.elem, a.nr
FROM   tbl AS t
LEFT   JOIN LATERAL unnest(string_to_array(t.elements, ',')) WITH ORDINALITY AS a(elem, nr) ON true

LEFT JOIN ... ON true 确保保留左侧表中的所有行,而不管右侧表表达式是否返回任何行。

或者,由于 LEFT JOIN ... ON true 保留了所有行,因此可以使用更简洁的查询版本:

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr)

对于实际数组(arr 为数组列),可以使用更简洁的形式:

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr)

为了简单起见,可以使用默认列名:

SELECT id, a, ordinality
FROM   tbl, unnest(arr) WITH ORDINALITY a

还可以进一步简化:

SELECT * FROM tbl, unnest(arr) WITH ORDINALITY a

此最终形式返回 tbl 的所有列。当然,显式指定列别名和表限定列可以提高清晰度。

a 既用作表别名,也用作列别名(对于第一列),附加的序号列的默认名称为 ordinality

PostgreSQL 8.4 - 9.3

使用 row_number() OVER (PARTITION BY id ORDER BY elem) 根据排序顺序(而不是序号位置)获取数字:

SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM  (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t

虽然这通常有效,并且在简单的查询中没有观察到失败,但 PostgreSQL 不保证在没有 ORDER BY 的情况下行的顺序。当前行为是实现细节的结果。

保证空格分隔字符串中元素的序号

SELECT id, arr[nr] AS elem, nr
FROM  (
   SELECT *, generate_subscripts(arr, 1) AS nr
   FROM  (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
   ) sub

对于实际数组,可以使用更简单的版本:

SELECT id, arr[nr] AS elem, nr
FROM  (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t

PostgreSQL 8.1 - 8.4

由于 PostgreSQL 8.1 到 8.4 版本缺少某些功能,例如 RETURNS TABLEgenerate_subscripts()unnest()array_length(),因此可以使用名为 f_unnest_ord 的自定义 SQL 函数:

CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1)   1
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i'

修改后的函数如下:

CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1)   1, i
 FROM   generate_series(array_lower($1,1), array_upper($1,1)) i'

此扩展函数 f_unnest_ord_idx 返回附加的 idx 列。比较:

SELECT id, arr, (rec).*
FROM  (
   SELECT *, f_unnest_ord_idx(arr) AS rec
   FROM  (
      VALUES
        (1, '{a,b,c}'::text[])  --  short for: '[1:3]={a,b,c}'
      , (2, '[5:7]={a,b,c}')
      , (3, '[-9:-7]={a,b,c}')
      ) t(id, arr)
   ) sub

输出

 id |       arr       | val | ordinality | idx
---- ----------------- ----- ------------ -----
  1 | {a,b,c}         | a   |          1 |   1
  1 | {a,b,c}         | b   |          2 |   2
  1 | {a,b,c}         | c   |          3 |   3
  2 | [5:7]={a,b,c}   | a   |          1 |   5
  2 | [5:7]={a,b,c}   | b   |          2 |   6
  2 | [5:7]={a,b,c}   | c   |          3 |   7
  3 | [-9:-7]={a,b,c} | a   |          1 |  -9
  3 | [-9:-7]={a,b,c} | b   |          2 |  -8
  3 | [-9:-7]={a,b,c} | c   |          3 |  -7
最新教程 更多>
  • 如何实时捕获和流媒体以进行聊天机器人命令执行?
    如何实时捕获和流媒体以进行聊天机器人命令执行?
    在开发能够执行命令的chatbots的领域中,实时从命令执行实时捕获Stdout,一个常见的需求是能够检索和显示标准输出(stdout)在cath cath cant cant cant cant cant cant cant cant interfaces in Chate cant inter...
    编程 发布于2025-04-13
  • 深入解析Worker Threads与子进程
    深入解析Worker Threads与子进程
    工作线程允许您在多个线程中运行JavaScript代码。它们非常适合通过共享ArhenArrayBuffer在线程之间共享内存,并用于卸载CPU结合的任务(例如数据处理或计算)。 [2 儿童进程使您能够产生单独的进程,从而独立于主node.js进程运行任务。它们适合需要隔离的任务或使用非JavaSc...
    编程 发布于2025-04-13
  • 从PHP中访问JavaScript变量的技巧
    从PHP中访问JavaScript变量的技巧
    Access a JavaScript Variable from PHPProblemAccessing JavaScript variables from PHP can be a challenge due to the inherent separation between server-s...
    编程 发布于2025-04-13
  • 为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    为什么我在Silverlight Linq查询中获得“无法找到查询模式的实现”错误?
    查询模式实现缺失:解决“无法找到”错误在银光应用程序中,尝试使用LINQ建立错误的数据库连接的尝试,无法找到以查询模式的实现。”当省略LINQ名称空间或查询类型缺少IEnumerable 实现时,通常会发生此错误。 解决问题来验证该类型的质量是至关重要的。在此特定实例中,tblpersoon可能需...
    编程 发布于2025-04-13
  • 如何使用Regex在PHP中有效地提取括号内的文本
    如何使用Regex在PHP中有效地提取括号内的文本
    php:在括号内提取文本在处理括号内的文本时,找到最有效的解决方案是必不可少的。一种方法是利用PHP的字符串操作函数,如下所示: 作为替代 $ text ='忽略除此之外的一切(text)'; preg_match('#((。 &&& [Regex使用模式来搜索特...
    编程 发布于2025-04-13
  • 如何正确使用与PDO参数的查询一样?
    如何正确使用与PDO参数的查询一样?
    在pdo 中使用类似QUERIES在PDO中的Queries时,您可能会遇到类似疑问中描述的问题:此查询也可能不会返回结果,即使$ var1和$ var2包含有效的搜索词。错误在于不正确包含%符号。通过将变量包含在$ params数组中的%符号中,您确保将%字符正确替换到查询中。没有此修改,PDO...
    编程 发布于2025-04-13
  • 如何有效地选择熊猫数据框中的列?
    如何有效地选择熊猫数据框中的列?
    在处理数据操作任务时,在Pandas DataFrames 中选择列时,选择特定列的必要条件是必要的。在Pandas中,选择列的各种选项。选项1:使用列名 如果已知列索引,请使用ILOC函数选择它们。请注意,python索引基于零。 df1 = df.iloc [:,0:2]#使用索引0和1 c...
    编程 发布于2025-04-13
  • 在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    编程 发布于2025-04-13
  • 在PHP中如何高效检测空数组?
    在PHP中如何高效检测空数组?
    在PHP 中检查一个空数组可以通过各种方法在PHP中确定一个空数组。如果需要验证任何数组元素的存在,则PHP的松散键入允许对数组本身进行直接评估:一种更严格的方法涉及使用count()函数: if(count(count($ playerList)=== 0){ //列表为空。 } 对...
    编程 发布于2025-04-13
  • HTML类顺序对CSS优先级有影响吗?
    HTML类顺序对CSS优先级有影响吗?
    Does Class Order in HTML Affect CSS Priority?In the realm of HTML and CSS, the order in which classes are listed on elements has been a topic of debat...
    编程 发布于2025-04-13
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-04-13
  • MySQL WHERE IN 子句如何使用ID数组?
    MySQL WHERE IN 子句如何使用ID数组?
    使用raray中的raray中QUERY mySQL的位置 步骤2:附加operator 步骤3:parameTerize values 使用准备好的语句或参数化query。 parameters.Example:SELECT * FROM galleriesSQL Query:WHERE id ...
    编程 发布于2025-04-13
  • 如何阻止网站图片被未授权下载?
    如何阻止网站图片被未授权下载?
    探索未经授权下载的最有效度量是避免在线发布它们,这可能总是可行的。假设有有限的漏洞水平,我们探索了其他技术,以阻碍图像下载并保障敏感或有价值的内容。一种常见的方法是在.gif或.png格式中使用透明的图像来叠加原始图像,从而从直接下载中掩盖了它。另一个选项涉及使用Background_image ...
    编程 发布于2025-04-13
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-04-13
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-04-13

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3