Postgres加入JSON列表

时间:2015-05-31 06:36:13

标签: json postgresql join

我在postgres 9.4中加入JSON列表时遇到问题

这是我的问题:

表格结构:

CREATE TABLE players
(
  id serial NOT NULL,
  player json,
  CONSTRAINT players_pkey PRIMARY KEY (id)
)

CREATE TABLE matches
(
  id serial NOT NULL,
  match json,
  CONSTRAINT matches_pkey PRIMARY KEY (id)
)

示例数据:

players
1;"{"Name":"AAA","Height":186,"Weight":65}"
2;"{"Name":"BBB","Height":195,"Weight":85}"
3;"{"Name":"CCC","Height":175,"Weight":72}"
4;"{"Name":"DDD","Height":168,"Weight":56}"

matches
5;{"Id":1,"Teams":[{"Name":"TeamA","Players":[{"Name":"AAA"},{"Name":"BBB"}]},{"Name":"TeamB","Players":[{"Name":"CCC"},{"Name":"DDD"}]}],"TeamRank":[1,2]}
6;{"Id":2,"Teams":[{"Name":"TeamA","Players":[{"Name":"CCC"},{"Name":"BBB"}]},{"Name":"TeamB","Players":[{"Name":"AAA"},{"Name":"DDD"}]}],"TeamRank":[1,2]}

每支球队的球员都是球队最后一场比赛中的球员。获取团队名称和玩家列表(当前团队)的查询如下:

SELECT DISTINCT ON (t.team->>'Name') t.team
FROM   matches m, json_array_elements(m.match->'Teams') t(team)
ORDER  BY t.team->>'Name', m.id DESC

返回以下(团队表):

"{"Name":"TeamA","Players":[{"Name":"CCC"},{"Name":"BBB"}]}"
"{"Name":"TeamB","Players":[{"Name":"AAA"},{"Name":"DDD"}]}"

我想在上面的结果中加入每个玩家的高度和重量,以便输出如下:

"{"Name":"TeamA","Players":[{"Name":"CCC","Height":175,"Weight":72},{"Name":"BBB","Height":195,"Weight":85}]}"
"{"Name":"TeamB","Players":[{"Name":"AAA","Height":186,"Weight":65},{"Name":"DDD","Height":168,"Weight":56}]}"

我尝试使用INNER JOIN执行此操作:

WITH u AS (SELECT DISTINCT ON (t.team->>'Name') t.team
FROM   matches m, json_array_elements(m.match->'Teams') t(team)   -- FROM ABOVE!!!
ORDER  BY t.team->>'Name', m.id DESC) 

SELECT player FROM (SELECT json_array_elements(team->'Players') FROM u) AS v
INNER JOIN players on v->>'Name'=player->>'Name';

这是我想要的一步,但是我收到以下错误:

ERROR: operator does not exist: record ->> unknown
SQL state: 42883
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Character: 2822

有人可以建议解决此问题或其他方法吗?

由于

1 个答案:

答案 0 :(得分:1)

此:

(SELECT json_array_elements(team->'Players') FROM u) AS v

v声明为关系,因此在其他地方对v的任何引用都将表示“此关系中的记录”。所以这个:

v->>'Name'=player->>'Name'

不起作用,因为它试图将v用作JSON值而不是记录。

要解决此问题,您需要使用列别名;例如,你可以写:

SELECT player FROM (SELECT json_array_elements(team->'Players') FROM u) AS v(v_player)
INNER JOIN players on v_player->>'Name' = player->>'Name';