Postgresql:按数字键值对 JSON 数组进行排序
Postgresql : Sorting JSON array by numeric key value
我一直在阅读类似的问题,这些问题看起来有足够简单的解决方案,但在这里应用它们似乎对我不起作用。
我在 postgres 数据库 table 中有一个 json 列,其中包含 x 和 y 坐标。在此列上执行简单的 select 会返回以下内容,例如:
[
{
"x": "-1.6827080672804147",
"y": "-0.011726425465745486"
},
{
"x": "2.4016256261667235",
"y": "0.016304356672382222"
},
{
"x": "0.2278035109735127",
"y": "0.0013854154958112177"
},
{
"x": "1.2104642489702613",
"y": "0.008129416140682903"
},
{
"x": "-0.3281865438803838",
"y": "-0.0024303442506510738"
},
{
"x": "-0.2401461868455415",
"y": "-0.0018261232803209514"
},
.
.
.
.
]
我想return这个对象按照x坐标升序排列。上面的结果集实际上是 运行 以下查询的结果:
SELECT coordinates
FROM schema_name.table_name
WHERE ....
AND ....
ORDER BY coordinates ->> 'x' asc;
我也试过使用
ORDER BY cast(coordinates->>'x' as numeric) ASC
产生以下结果:
ERROR: cannot cast type json to numeric
我确定我错过了一些愚蠢的东西。任何正确方向的指示将不胜感激。
由于所有这些元素都在一个字段中,通过对其进行排序,您正在转换数据,因此您需要将其拆开、排序,然后将其放回原处。
SELECT ('[' || STRING_AGG(j::TEXT, ',' ORDER BY (j->>'x')::NUMERIC) || ']')::JSON
FROM json_array_elements(
'[
{"x": "2.4016256261667235","y": "0.016304356672382222"},
{"x": "-1.6827080672804147","y": "-0.011726425465745486"},
{"x": "0.2278035109735127","y": "0.0013854154958112177"}
]'::JSON) j
结果:
[{"x": "-1.6827080672804147","y": "-0.011726425465745486"},{"x": "0.2278035109735127","y": "0.0013854154958112177"},{"x": "2.4016256261667235","y": "0.016304356672382222"}]
我应该指出,我 认为 在以后的 PG 版本中可能有比 STRING_AGG 更好的方法来构建 JSON 对象,但是我用的是PG 9.3,所以...
您应该在 json_agg()
中使用 order by
。您可能想要定义一个在各种情况下都有用的函数:
create or replace function sort_my_array(json)
returns json language sql immutable as $$
select json_agg(value order by (value->>'x')::numeric)
from json_array_elements()
$$;
select sort_my_array(coordinates)
from my_table
如果您不喜欢自定义函数,请在横向连接中使用 json_array_elements()
:
select json_agg(value order by (value->>'x')::numeric)
from my_table
cross join json_array_elements(coordinates)
中测试
我一直在阅读类似的问题,这些问题看起来有足够简单的解决方案,但在这里应用它们似乎对我不起作用。 我在 postgres 数据库 table 中有一个 json 列,其中包含 x 和 y 坐标。在此列上执行简单的 select 会返回以下内容,例如:
[
{
"x": "-1.6827080672804147",
"y": "-0.011726425465745486"
},
{
"x": "2.4016256261667235",
"y": "0.016304356672382222"
},
{
"x": "0.2278035109735127",
"y": "0.0013854154958112177"
},
{
"x": "1.2104642489702613",
"y": "0.008129416140682903"
},
{
"x": "-0.3281865438803838",
"y": "-0.0024303442506510738"
},
{
"x": "-0.2401461868455415",
"y": "-0.0018261232803209514"
},
.
.
.
.
]
我想return这个对象按照x坐标升序排列。上面的结果集实际上是 运行 以下查询的结果:
SELECT coordinates
FROM schema_name.table_name
WHERE ....
AND ....
ORDER BY coordinates ->> 'x' asc;
我也试过使用
ORDER BY cast(coordinates->>'x' as numeric) ASC
产生以下结果:
ERROR: cannot cast type json to numeric
我确定我错过了一些愚蠢的东西。任何正确方向的指示将不胜感激。
由于所有这些元素都在一个字段中,通过对其进行排序,您正在转换数据,因此您需要将其拆开、排序,然后将其放回原处。
SELECT ('[' || STRING_AGG(j::TEXT, ',' ORDER BY (j->>'x')::NUMERIC) || ']')::JSON
FROM json_array_elements(
'[
{"x": "2.4016256261667235","y": "0.016304356672382222"},
{"x": "-1.6827080672804147","y": "-0.011726425465745486"},
{"x": "0.2278035109735127","y": "0.0013854154958112177"}
]'::JSON) j
结果:
[{"x": "-1.6827080672804147","y": "-0.011726425465745486"},{"x": "0.2278035109735127","y": "0.0013854154958112177"},{"x": "2.4016256261667235","y": "0.016304356672382222"}]
我应该指出,我 认为 在以后的 PG 版本中可能有比 STRING_AGG 更好的方法来构建 JSON 对象,但是我用的是PG 9.3,所以...
您应该在 json_agg()
中使用 order by
。您可能想要定义一个在各种情况下都有用的函数:
create or replace function sort_my_array(json)
returns json language sql immutable as $$
select json_agg(value order by (value->>'x')::numeric)
from json_array_elements()
$$;
select sort_my_array(coordinates)
from my_table
如果您不喜欢自定义函数,请在横向连接中使用 json_array_elements()
:
select json_agg(value order by (value->>'x')::numeric)
from my_table
cross join json_array_elements(coordinates)
中测试