22

我在匹配表中有以下数据:

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]}

我想按名称选择表中每个最后一个不同的团队。即我想要一个将返回的查询:

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

因此,上次该团队出现在表格中的每个团队。
我一直在使用以下(从这里):

WITH t AS (SELECT id, json_array_elements(match->'Teams') AS team FROM matches)
SELECT MAX(id) AS max_id, team FROM t GROUP BY team->'Name';

但这会返回:

ERROR: could not identify an equality operator for type json
SQL state: 42883
Character: 1680

我知道 Postgres没有 JSON 相等性。我只需要球队名称(一个字符串)的相等性,该球队的球员不需要进行比较。

谁能建议另一种方法来做到这一点?
以供参考:

SELECT id, json_array_elements(match->'Teams') AS team FROM matches

返回:

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

编辑:我投到text并关注这个问题,我用DISTINCT ON而不是GROUP BY. 这是我的完整查询:

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

返回我上面想要的。有没有人有更好的解决方案?

4

1 回答 1

15

更短、更快、更优雅的LATERAL连接:

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;  -- to get the "last"

如果你只想要不同的团队,ORDER BY可以去。有关的:

JSON 和相等性

Postgres中的数据类型没有相等运算符json,但jsonb(Postgres 9.4+)有一个:

于 2015-05-29T03:45:17.240 回答