【问题标题】:Custom ordering by JSON column's array of objects in PostgreSQL按 PostgreSQL 中 JSON 列的对象数组自定义排序
【发布时间】:2020-08-07 16:00:35
【问题描述】:

我在 PostgreSQL 10.9 数据库的表中有一个 json 数据类型的 json_metrics 列。列中的数据是一个对象数组,每个对象都有一个会话、入口、月份和年份属性。每个月/年组合最多有一个对象。所以它看起来像这样,例如:

[
  {"sessions":52,"entrances":55,"month":3,"year":2020},
  {"sessions":59,"entrances":59,"month":4,"year":2020},
  {"sessions":76,"entrances":76,"month":5,"year":2020}
]

我希望能够对存储在此 json_metrics 列中的给定“月”和“年”组合的“会话”或“入口”上的行进行排序。例如。按 3/2020 会话降序对行进行排序。如果有一个关于 sessions-2020-03 的专栏,我当然会只使用“order by sessions-2020-03 desc”来做到这一点。

我试图用 json 列做的事情可能吗?我愿意更改 json 的结构,或者将数据类型更改为 jsonb(如果有任何值)。

【问题讨论】:

  • 有可能。如果您使用的是 PG12,那么您可以使用 SQL jsonpath 为您提取正确的对象,然后直接取消引用 sessions 键。如果您在较早的 PG 上,则需要在横向连接中使用 json_array_elements() 将此数组转换为行并使用 where 子句对其进行过滤,然后使用 order by。我想帮忙举个例子,但我需要用完一天。
  • 感谢您的建议@MikeOrganek。我应该包括我使用的是 10.9 版本,所以听起来这可能会变得混乱。 :) 我将不得不尝试沿着这条路走下去,看看它是如何进行的,也许比较是否有更好的方法来组织 json,或者如果获取所有行然后在代码中排序会更好。
  • 一点也不差。 jsonpath 会更容易,但取消嵌套只是一个额外的步骤。

标签: json postgresql


【解决方案1】:

使用 PG10,我会这样处理问题:

select mt.*
  from my_table mt
 cross join lateral json_array_elements(my_json_stuff) as j(obj)
 where ((obj->>'year')::int, (obj->>'month')::int) = (2020, 3)
 order by (obj->>'sessions')::int desc;

针对您的评论,如果您想保留没有2020-03 条目的行,那么您可以执行left join lateral,其行为类似于left joinlateral 为您购买到包含被爆出的 json 类型的行的隐式连接。

select mt.*
  from my_table mt
  left join lateral json_array_elements(my_json_stuff) as j(obj)
    on ((obj->>'year')::int, (obj->>'month')::int) = (2020, 3)
 order by (obj->>'sessions')::int desc nulls last;

另一个注意事项:您确实希望使用 jsonb 而不是 json 继续前进。

【讨论】:

  • 难以置信!所以,我已经放弃了,用代码做的工作不如这个。但是,以上似乎确实排除了不匹配的结果(2020, 3)。您是否可以提出一个不会过滤掉它们但将它们留在这些排序行下方的修改?我不想在返回的整体数据中添加额外的“where”子句。
  • @mmccaff 抱歉这么晚了——我一整天都在外面。我添加了一个使用left join lateral 的示例,该示例适用于我制作的示例。如果给您带来问题,请在 cmets 中告诉我。
  • 完美,我希望我可以给多个赞成票!感谢您对此提供的帮助,PostgreSQL 处理这种情况真是太好了。顺便说一句,性能将是使用 jsonb 而非 json 的主要优势吗?有什么缺点吗?
  • @mmccaff 是的。性能是jsonb 优于json 的主要优势。常规的json 可能比jsonb 具有大小优势。也就是说,使用calendar 表和metrics 表建立关系将在性能和大小方面掩盖这两种 json 类型。
猜你喜欢
  • 2018-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
  • 2018-08-10
相关资源
最近更新 更多