0

我有一个t包含一些列的表ab并且c。我使用以下查询将行转换为 JSON 对象数组:

SELECT COALESCE(JSON_AGG(t ORDER BY c), '[]'::json)
FROM   t

这将按预期返回:

[
  {
    "a": ...,
    "b": ...,
    "c": ...
  },
  {
    "a": ...,
    "b": ...,
    "c": ...
  }
]

现在我想要相同的结果,但只有列ab输出。我仍将使用列c进行排序。我想出的最好的方法如下:

SELECT COALESCE(JSON_AGG(JSON_BUILD_OBJECT('a', a, 'b', b) ORDER BY c), '[]'::json)
FROM   t

[
  {
    "a": ...,
    "b": ...
  },
  {
    "a": ...,
    "b": ...
  }
]

虽然这很好用,但我想知道是否有更优雅的方法来做到这一点。让我感到沮丧的是,我必须手动定义 JSON 属性。当然,我知道我必须枚举列ab,但奇怪的是我必须复制/粘贴相应的 JSON 属性名,无论如何这与列名完全相同。

还有另一种方法可以做到这一点吗?

4

2 回答 2

1

您可以使用 row_to_json 而不是手动构建对象:

CREATE TABLE foobar (a text, b text, c text);

INSERT INTO foobar VALUES 
    ('1', 'LOREM', 'A'),
    ('2', 'LOREM', 'B'),
    ('3', 'LOREM', 'C');

--Using CTE
WITH tmp AS (
    SELECT a, b FROM foobar ORDER BY c
)
SELECT json_agg(row_to_json(t)) FROM tmp t

--Using subquery
SELECT 
    json_agg(row_to_json(t)) 
FROM 
    (SELECT a, b FROM foobar ORDER BY c) t;

编辑:正如你所说,结果顺序是一项严格的要求。在这种情况下,您可以使用行构造函数来构建 json 对象:

--Using a type to build json with desired keys
CREATE TYPE mytype AS (a text, b text);

SELECT 
    json_agg(
        to_json(
            CAST(
                ROW(a, b) AS mytype
            ) 
        )
    ORDER BY c) 
FROM 
    foobar;

--Ignoring column names...    
SELECT 
    json_agg(
        to_json(
            ROW(a, b) 
        )
    ORDER BY c) 
FROM 
    foobar;

SQL Fiddle在这里

于 2018-04-02T17:51:27.723 回答
0

在子查询或 cte 中执行排序,然后应用json_agg

SELECT COALESCE(JSON_AGG(t2), '[]'::json)
FROM (SELECT a, b FROM t ORDER BY c) t2

或者使用 jsonb。jsonb 类型允许通过指定它们的键来删除项目

SELECT coalesce(jsonb_agg(row_to_json(t)::jsonb - 'c' 
                          order by c), '[]'::jsonb)
FROM t
于 2018-04-02T17:52:39.263 回答