Postgresql 9.6:查询JSONB数组的特定范围

时间:2017-10-27 14:42:49

标签: postgresql jsonb

我目前使用Postgresql 9.6并且一直在尝试从几小时后以最有效的方式解决以下问题:

我的示例表:

id | data
-----------------------------------------------------------------------------------------------------------
10 | {"scores": [{"u": "Peter", s: 120}, {"u": "Joe", s: 100}, {"u": "Pam", s: 70}, {"u": "Lisa", s: 120}]}
11 | {"scores": [{"u": "Mae", s: 320}, {"u": "Max", s: 230}, {"u": "Moe", s: 170}, {"u": "Mini", s: 120}]}
12 | {"scores": [{"u": "Jack", s: 140}, {"u": "John", s: 110}, {"u": "Wes", s: 70}, {"u": "Mick", s: 20}]}

我需要一个查询来获取每行的前2个用户名(u)。

所以我的结果应该是这样的:

users
-----
Peter
Joe
Mae
Max
Jack
John

获取第二个和第三个用户名的查询:

users
-----
Joe
Pam
Max
Moe
John
Wes

解决这个问题的最有效方法是什么?我的真实表格包含100-400个元素和大约1500行。

1 个答案:

答案 0 :(得分:4)

前2个用户名:

SELECT scores -> 'u'
FROM (
  SELECT  ROW_NUMBER() OVER(PARTITION BY id) rn, scores
  FROM (
    SELECT id, data, jsonb_array_elements(data -> 'scores') AS scores
    FROM scores
  ) s1
) s2
WHERE rn <= 2;

第二和第三个用户名:

SELECT scores -> 'u'
FROM (
  SELECT  ROW_NUMBER() OVER(PARTITION BY id) rn, scores
  FROM (
    SELECT id, data, jsonb_array_elements(data -> 'scores') AS scores
    FROM scores
  ) s1
) s2
WHERE rn = 2 OR rn = 3;

另一种选择是:

SELECT username
FROM (
  SELECT unnest(ARRAY [(data #> '{scores,0,u}') :: TEXT, (data #> '{scores,1,u}') :: TEXT]) username
  FROM scores
) usernames WHERE username NOTNULL;

第二和第三个用户名:

SELECT username
FROM (
  SELECT unnest(ARRAY [(data #> '{scores,1,u}') :: TEXT, (data #> '{scores,2,u}') :: TEXT]) username
  FROM scores
) usernames WHERE username NOTNULL;