在Postgres中的GROUP BY操作 - JSON数据类型没有相等性?
在Postgres中的GROUP BY操作 - JSON数据类型没有相等性?
我在一个匹配表中有以下数据:
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;
返回了我想要的结果。有人有更好的解决方案吗?
GROUP BY在Postgres中的使用存在问题,特别是对于JSON数据类型。JSON数据类型在Postgres中没有等号运算符,但是在Postgres 9.4+版本中有一个针对JSONB数据类型的等号运算符。
解决方法是使用LATERAL连接来实现更简洁、更快速、更优雅的查询。通过使用LATERAL连接和json_array_elements函数,可以实现对JSON数组中的元素进行GROUP BY操作。以下是使用LATERAL连接进行GROUP BY操作的示例代码:
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;
上述代码中,我们通过LATERAL连接将JSON数组中的元素进行展开,并对展开后的元素进行GROUP BY操作。通过DISTINCT ON子句,我们可以获取每个组中的第一个元素。通过ORDER BY子句,我们可以按照指定的字段进行排序,以获取每个组中的最后一个元素。
如果只需要获取不重复的团队信息,可以省略ORDER BY子句。通过使用LATERAL连接和json_array_elements函数,我们可以轻松地对JSON数组中的元素进行GROUP BY操作。
关于JSON和等号运算符的问题,我们可以使用jsonb数据类型来解决。在Postgres 9.4+版本中,jsonb数据类型具有等号运算符。如果需要对json数据类型进行等号比较,可以将其强制转换为jsonb数据类型。以下是将json数据类型强制转换为jsonb数据类型的示例代码:
my_json_column::jsonb
通过将json数据类型转换为jsonb数据类型,我们可以在某些情况下使用等号运算符进行比较操作。
总结起来,GROUP BY在Postgres中对于JSON数据类型存在问题,但是可以通过使用LATERAL连接来解决。此外,json数据类型没有等号运算符,但是可以通过将其转换为jsonb数据类型来实现等号比较操作。通过上述方法,我们可以更方便地对JSON数据类型进行GROUP BY操作和等号比较操作。