简体   繁体   English

Postgres 加入 json 数组值

[英]Postgres join on json array values

I have a table users as follows:我有一个表users如下:

|  id  |        name         |
|  1   |  Marvin Hargraves   |
|  2   |  Lincoln Clayton    |
|  3   |  Frank Pearce       |

And a table posts where I got json column with attributes:还有一张表格,我在其中获得了带有属性的posts列:

|  id   |        attributes       | content |
|  11   | {"user_ids":["1", "2"]} |  "xyz"  |
|  12   | {"user_ids":["1", "3"]} |  "xyz"  |

Id's in the array reference the user from users table.数组中的 ID 引用users表中的用户。 I need to display user names instead of IDs like:我需要显示用户名而不是 ID,例如:

    |  id   |                 users                   |
as an array
    |  11   | ["Marvin Hargraves", "Lincoln Clayton"] |
or string
    |  12   | "Marvin Hargraves, Frank Pearce"        |

I'm using PostgreSQL version 10.我正在使用 PostgreSQL 版本 10。
I tried this query:我试过这个查询:

SELECT p.id, 
  (SELECT array_agg(array[u.name])
   FROM post AS p
   JOIN user u ON u.id = ANY(p.attributes->'user_ids')
   GROUP BY p.id) AS users
FROM post p

But I got the following error:但我收到以下错误:

 ERROR: op ANY/ALL (array) requires array on right side

You will need to use jsonb_array_elements_text to unpack the jsonb array, join to users, and then aggregate it back together:您将需要使用 jsonb_array_elements_text 解压缩 jsonb 数组,加入用户,然后将其聚合回来:

SELECT p.id, array_agg(name ORDER BY i) as users
FROM post p
-- Use WITH ORDINALITY to preserve the order of the original array
CROSS JOIN LATERAL jsonb_array_elements_text(p.attributes->'user_ids') WITH ORDINALITY AS j(user_id, i)
JOIN users ON users.id = j.user_id::int
GROUP BY p.id
;

Here's a fiddle .这是一个小提琴

I suggest to use an ARRAY constructor in a LATERAL subquery:我建议在LATERAL子查询中使用ARRAY 构造函数

SELECT p.id, j.users
FROM   post p
CROSS  JOIN LATERAL (
   SELECT ARRAY(
      SELECT u.name
      FROM   jsonb_array_elements_text(p.attributes->'user_ids') WITH ORDINALITY j(user_id, ord)
      JOIN   users u ON u.id = j.user_id::int
      ORDER  BY j.ord
      ) AS users
   ) j
;

db<>fiddle here db<> 在这里摆弄

Note that null values in the array are ignored.请注意,数组中的null值将被忽略。

The CROSS JOIN never eliminates rows in this case because the ARRAY constructor always returns a row, even when the JSON array is empty or NULL.在这种情况下, CROSS JOIN永远不会消除行,因为 ARRAY 构造函数总是返回一行,即使 JSON 数组为空或 NULL 也是如此。

Related:有关的:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM