如何在 ARRAY_AGG 表达式中定义别名?

Joh*_*ith 5 postgresql postgresql-9.2

我正在尝试从 Postgres 9.2 表中返回纯 JSON。

  SELECT ARRAY_TO_JSON(ARRAY_AGG(ALBUM_ROW))
  FROM (
    SELECT
      album,
      max(release_year) AS release_year,
      max(artwork_path) AS artwork_path,
      MD5(concat(album,release_year,artist)) AS token,
      ARRAY_AGG((media_files.position, media_files.token, media_files.title) ORDER BY media_files.position) as media_files
    FROM media_files
    INNER JOIN playlist_media_files ON playlist_media_files.media_file_id = media_files.id
    WHERE playlist_media_files.playlist_id = 1
    GROUP BY album, release_year, artist
    ORDER BY artist, release_year
  ) as ALBUM_ROW
Run Code Online (Sandbox Code Playgroud)

这个查询工作得很好,但是就行了:

ARRAY_AGG((media_files.position, media_files.token) ORDER ...) as media_files
Run Code Online (Sandbox Code Playgroud)

我想在结果集中别名positiontoken属性。

AS 显然这里是不允许的。

我会写:

ARRAY_AGG((media_files.position AS xxx, media_files.token AS yyy) ORDER BY media_files.position) as media_files
Run Code Online (Sandbox Code Playgroud)

但它不起作用。

Postgres 文档说:“其中aggregate_name 是先前定义的聚合(可能用模式名称限定),表达式是任何本身不包含聚合表达式或窗口函数调用的值表达式,order_by_clause 是可选的 ORDER BY 子句,如上所述以下。”

http://www.postgresql.org/docs/9.3/static/sql-expressions.html#SYNTAX-AGGREGATES

我倒霉了吗?

Erw*_*ter 6

您正在使用以下表达式形成临时行类型(实际上是匿名记录):

(media_files.position, media_files.token, media_files.title)
Run Code Online (Sandbox Code Playgroud)

在您的聚合函数调用中:

ARRAY_AGG((media_files.position, media_files.token, media_files.title)
          ORDER BY media_files.position) AS media_files
Run Code Online (Sandbox Code Playgroud)

数组类型只能建立在众所周知的类型上。您的选择是向系统通告这种类型并在形成数组之前将记录转换为它。创建一个众所周知的复合类型

CREATE TYPE my_type AS (
  position int    -- data type?
 ,token    text
 ,title    text
 )
Run Code Online (Sandbox Code Playgroud)

我猜测这里缺乏信息的数据类型。填写您的实际类型。

创建表具有相同的效果:它也间接地向系统宣布一个众所周知的复合类型。因此,您可以(ab-)使用临时表在会话期间注册复合类型:

CREATE TEMP TABLE my_type AS (
  position int    -- data type?
 ,token    text
 ,title    text
 )
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,您都可以投射您的记录:

ARRAY_AGG((media_files.position, media_files.token, media_files.title)::my_type
          ORDER BY media_files.position) AS media_files
Run Code Online (Sandbox Code Playgroud)

然后你可以通过名称引用(现在众所周知的)类型的元素:

SELECT media_files[1].position, media_files[1].token
FROM  (
     ...
   ,ARRAY_AGG((media_files.position, media_files.token, media_files.title)::my_type
          ORDER BY media_files.position) AS media_files
   ...
   FROM ....
   GROUP BY ...
  ) sub;
Run Code Online (Sandbox Code Playgroud)

现在,Postgres 可以使用这些名称来构建 JSON 值。瞧。