注意:我使用的是Postgres的最新版本(9.4)
我正在尝试编写一个查询,它通过第一个表的主键执行2个表和组的简单连接,并在第二个表中执行我想要作为对象返回的几个字段的array_agg。数组需要通过json对象中的2个字段的组合进行排序,并且也是未经过调整的。
到目前为止,我已经提出以下建议:
SELECT
zoo.id,
ARRAY_AGG(
DISTINCT ROW_TO_JSON((
SELECT x
FROM (
SELECT animals.type, animals.name
) x
))::JSONB
-- ORDER BY animals.type, animals.name
)
FROM zoo
JOIN animals ON animals.zooId = zoo.id
GROUP BY zoo.id;
这导致每个动物园有一行,一个jsonb对象的聚合数组,每个动物一个,唯一。
但是,我似乎无法弄清楚如何通过代码注释部分中的参数对其进行排序。
如果我拿出不同的,我可以ORDER BY原始字段,这很好用,但后来我有重复。
答案 0 :(得分:2)
如果您使用row_to_json()
,除非您输入一行,否则您将丢失列名。如果你"手动"使用显式名称使用jsonb
构建json_build_object()
对象,然后将其取回:
SELECT zoo.id, array_agg(za.jb) AS animals
FROM zoo
JOIN (
SELECT DISTINCT ON (zooId, "type", "name")
zooId, json_build_object('animal_type', "type", 'animal_name', "name")::jsonb AS jb
FROM animals
ORDER BY zooId, jb->>'animal_type', jb->>'animal_name'
-- ORDER BY zooId, "type", "name" is far more efficient
) AS za ON za.zooId = zoo.id
GROUP BY zoo.id;
您可以ORDER BY
jsonb
对象的元素,如上所示,但是(据我所知)您不能在DISTINCT
对象上使用jsonb
。在你的情况下,无论如何这将是相当低效的(首先构建所有jsonb
个对象,然后丢弃重复项)并且在聚合级别上,使用标准SQL几乎是不可能的。但是,通过在构建DISTINCT
对象之前应用jsonb
子句,可以获得相同的结果。
另外,请避免使用SQL key words类似"类型"和标准数据类型,如" name"作为列名。两者都是非保留关键字,因此可以在适当的上下文中使用它们,但实际上你的命令可能会让人感到困惑。例如,您可以拥有一个模式,一个表,一个表中的一列,以及一个数据类型,每个数据都被称为"类型"然后你就可以得到这个:
SELECT type::type FROM type.type WHERE type = something;
虽然PostgreSQL会慷慨地接受这一点,但它在最好的情况下很容易混淆,并且在各种更复杂的情况下容易出错。你可以通过重复引用任何关键词来获得很长的路要走,但最好不要将它们作为标识符来避免。