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

Phi*_*erg 5 postgresql distinct sql-order-by 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;
Run Code Online (Sandbox Code Playgroud)

这导致每个动物园有一行,其中一个jsonb对象的聚合数组,每个动物一个,唯一.

但是,我似乎无法弄清楚如何通过代码注释掉的部分中的参数对其进行排序.

如果我拿出不同的,我可以ORDER BY原始字段,这很好,但后来我有重复.

Pat*_*ick 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;
Run Code Online (Sandbox Code Playgroud)

您可以使用对象ORDER BY的元素jsonb,如上所示,但是(据我所知)您不能DISTINCTjsonb对象上使用。在你的情况下,无论如何,这都是相当低效的(首先构建所有jsonb对象,然后丢弃重复项),并且在聚合级别上,使用标准 SQL 显然是不可能的。DISTINCT但是,通过在构建对象之前应用该子句,您可以获得相同的结果jsonb

另外,避免使用SQL 关键字(例如“type”)和标准数据类型(例如“name”)作为列名称。两者都是非保留关键字,因此您可以在适当的上下文中使用它们,但实际上您的命令可能会变得非常混乱。例如,您可以有一个模式,其中包含一个表、该表中的一列以及一个称为“type”的数据类型,然后您可以得到:

SELECT type::type FROM type.type WHERE type = something;
Run Code Online (Sandbox Code Playgroud)

虽然 PostgreSQL 会慷慨地接受这一点,但它充其量只是令人困惑,并且在各种更复杂的情况下容易出错。通过双引号任何关键字可以得到很大的帮助,但最好避免将它们作为标识符。