如何在postgresSQL中的jsonb值的array_agg中组合DISTINCT和ORDER BY

时间:2015-05-16 06:38:54

标签: postgresql sql-order-by distinct aggregate-functions jsonb

注意:我使用的是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原始字段,这很好用,但后来我有重复。

1 个答案:

答案 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会慷慨地接受这一点,但它在最好的情况下很容易混淆,并且在各种更复杂的情况下容易出错。你可以通过重复引用任何关键词来获得很长的路要走,但最好不要将它们作为标识符来避免。