如何根据对象的属性对 json 或 jsonb 值内的数组中的对象进行排序?

2023-11-23

我有这个 pl/pgsql 函数来聚合两个表中的行jsonb value (data_table_1 and data_table_2). fk_id是两个表中的公共外键 id:

DECLARE
v_my_variable_1 jsonb;
v_my_variable_2 jsonb;
v_combined      jsonb;
BEGIN
  SELECT json_agg( data_table_1 ) INTO v_my_variable FROM data_table_1 WHERE fk_id = v_id;
  SELECT json_agg( data_table_2 ) into v_my_variable_2 FROM data_table_2 WHERE fk_id = v_id;
  SELECT v_my_variable || v_my_variable_2 into v_combined;

现在我想排序v_combined由田地ts,两个表共有的时间戳列,因此是所有数组对象中的公共键jsonb value.

Example:

v_combined = '[{"id": 1, "type": 4, "param": 3, "ts": 12354355}
             , {"id": 1, "txt": "something", "args": 5, "ts": 12354345}]';

如何对数组元素进行排序v_combined按升序排列ts?

如果我从表中选择,我可以简单地使用:

select * into v_combined from v_combined ORDER BY v_combined->>'ts' ASC;

但当我尝试这样做时,它说v_combined不存在。有没有办法将其存储在临时表中并在那里排序,或者有没有直接的方法对 pl/pgsql 中的 json 对象数组进行排序?


The 对象中键的顺序 in a jsonb文字是微不足道的 - 对象键无论如何都在内部排序。 (json在这方面有所不同。)参见:

  • 自定义涉及数组的 jsonb 键排序顺序

The 数组元素的顺序 in a jsonb (or json) 不过,字面意思很重要。你的要求很有意义。您可以像这样重新排序:

SELECT jsonb_agg(elem)
FROM  (
   SELECT *
   FROM   jsonb_array_elements(v_combined) a(elem)
   ORDER  BY (elem->>'ts')::int  -- order by integer value of "ts"
   ) sub;

数据库小提琴here

但它会是更高效对数组进行排序before分配它:

...
DECLARE
   v_combined      jsonb;
BEGIN
   SELECT INTO v_combined  jsonb_agg(elem)
   FROM  (
      SELECT ts, json_agg(data_table_1) AS j
      FROM   data_table_1
      WHERE  fk_id = v_id

      UNION ALL 
      SELECT ts, json_agg(data_table_2)
      FROM   data_table_2
      WHERE  fk_id = v_id
      ORDER  BY ts
      ) sub;
...

根据子查询中的行的顺序

在标准 SQL 中行的顺序在子查询(或任何表表达式)中也是微不足道的。但在 Postgres 中,子查询中的行顺序被转移到下一个级别。所以这适用于简单的查询。是均匀的有记录的:

...从排序子查询提供输入值通常会起作用。例如:

SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;

请注意,如果外部查询级别包含附加处理(例如联接),则此方法可能会失败,因为这可能会导致子查询的输出在计算聚合之前重新排序。

如果您不能或不会依赖于此,还有一个安全的替代方案:添加ORDER BY到聚合函数本身。那就更短了:

SELECT INTO v_combined  jsonb_agg(elem  ORDER BY (elem->>'ts')::int)
FROM   jsonb_array_elements(v_combined) a(elem);

但这通常是slower.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何根据对象的属性对 json 或 jsonb 值内的数组中的对象进行排序? 的相关文章

随机推荐

  • 如何在经典 ASP 中使变量静态(或“全局”)?

    我想让我的变量静态或 全局 因此与 NET 中的静态效果相同 访问它的每个会话都会得到相同的结果 如果一个会话修改它 它也会影响其他所有人 如何在经典 ASP 中实现这一目标 如果您想要一个可在应用程序范围内访问的变量 则可以使用应用程序对
  • 在 numpy 数组中设置空值

    如何根据条件将 numpy 数组中的某些值设为 null 我不明白为什么在不满足条件的情况下我最终会得到 0 而不是 null 或空值 b 是一个填充有 0 和 1 值的 numpy 数组 c 是另一个完全填充的 numpy 数组 所有阵列
  • Visual Studio 2008 中的 WatiN - 第二个测试方法失败

    当尝试在 Visual Studio 2008 中运行一个非常简单的 WatiN 2 0 CTP3 测试时 我发现第一个测试总是执行得很好 第二个测试方法似乎破坏了 IE 对象中的某些内容 产生以下异常 测试方法 testProject W
  • 如何使用自定义 IXmlSerialized 作为 XmlAttribute?

    我实施IXmlSerializable对于以下将 RGB 颜色值编码为单个字符串的类型 public class SerializableColor IXmlSerializable public int R get set public
  • 安装 Tensorflow 时出错 - Python 3.8

    我是编程新手 正在学习必须安装 Tensorflow 的课程 问题是我正在使用 Python 3 8 据我所知 Tensorflow 不支持它 我已经下载了 Python 3 6 但我不知道如何将其切换为默认的 python 版本 最好使用
  • 不同文化中的 JavaScript parseFloat

    我对 JavaScript 的 parseFloat 函数在世界不同地区的默认行为有疑问 在美国 如果对字符串 123 34 调用 parseFloat 您将得到浮点数 123 34 如果我在瑞典或巴西开发代码 并且他们使用逗号而不是句点作
  • 是否可以“git diff”2 个字符串?

    我有 2 个字符串 我想要它们之间的 git diff 我可以创建 file1 并添加 string1 作为其内容 然后我可以创建 file2 并添加 string2 作为其内容 然后我可以 git diff file1 和 file2 但
  • 配置错误:未满足包要求(sqlite3 > 3.7.4)

    我正在尝试按照以下说明在 Centos 7 上安装 php https www php net manual en install unix nginx php 我的nginx版本 nginx 1 19 0 我从下载了 php 7 4 6
  • React:useState 还是 useRef?

    我正在阅读有关 React 的内容useState and useRef at 挂钩常见问题解答 我对一些用例感到困惑 这些用例似乎同时具有 useRef 和 useState 的解决方案 而且我不确定哪种方式是正确的 来自 Hook 常见
  • 使两列高度相同

    我正在尝试制作 2 列设计 使用推特引导程序 有 2 根等高的柱子 让我们看这个例子 div class row fluid div class span2 ul li Item 1 li li Item 2 li li Item 3 li
  • 如何在依赖检查之前运行 Maven 插件

    我想在依赖项检查之前运行 maven install plugin 我怎样才能做到这一点 插件配置
  • 如何删除轮廓 mat-form-field 边框角半径

    我正在使用角材料轮廓垫形式场来设计形式 我得到了带有边框角半径的默认 mat form field 轮廓文本框视图 有什么方法可以删除轮廓 mat form field 的边框角半径并转换为方形文本框视图 我尝试使用以下内容更改角度材料 m
  • 在 XPath 中通过 concat() 换行(\n)?

    所以我的系统中有一个员工的 XML 文档
  • 如何在phpmyadmin中设置max_allowed_pa​​cket?

    我必须改变max allowed packetMySQL 中的大小使用phpmyadmin 但我不知道该怎么做 当我尝试时set global max allowed packet 10M in phpmyadmin它给出了这个错误 122
  • RMI 中可以通过引用传递吗?

    我读过各种有关使用 RMI 传递变量的文章 有些人说在 RMI 中不可能通过引用传递变量 例如 this one and this one 而其他人则说这是可能的 例如 this one this one and this one 有人可以
  • 使用唯一/随机名称存储文件

    使用新的 Firebase API 您可以从客户端代码将文件上传到云存储 这examples假设文件名在上传期间是已知的或静态的 Create a root reference var storageRef firebase storage
  • 如何使用语言环境将日期转换为 go 中的字符串?

    我这样将日期转换为字符串 d Format Mon 02 Jan 我得到类似的东西 Fri 27 Jan 如何切换区域设置并获取其他语言的字符串 你不能 Go 标准库不包含本地化的月份 日期和区域名称 这些名称被连接到time包裹 例如 返
  • NHibernate 无法将 MySQL 日期/时间值转换为 System.DateTime

    我收到 无法将 MySQL 日期 时间值转换为 System DateTime 错误 因为据我所知 我有一条 0000 00 00 00 00 00 的记录 现在 虽然数据不应该是这样的 它应该为空 但在某些情况下可能会发生这种情况 我不希
  • 如何从googletest中的异常中获取回溯信息?

    我正在尝试做一些半测试驱动的设计 有时当我实现一个新功能时 它会在某个地方出现异常 gtest 告诉我的只是异常是什么 并且没有给我任何回溯信息 如果我运行 gdb args gtest catch exceptions 0 它将在出现异常
  • 如何根据对象的属性对 json 或 jsonb 值内的数组中的对象进行排序?

    我有这个 pl pgsql 函数来聚合两个表中的行jsonb value data table 1 and data table 2 fk id是两个表中的公共外键 id DECLARE v my variable 1 jsonb v my