Sql 转换为JSON时如何使用行列的子集?

Sql 转换为JSON时如何使用行列的子集?,sql,json,postgresql,jsonb,postgresql-json,Sql,Json,Postgresql,Jsonb,Postgresql Json,我有一个表t,其中有一些列a、b和c。我使用以下查询将行转换为对象的JSON数组: SELECT COALESCE(JSON_AGG(t ORDER BY c), '[]'::json) FROM t 这将如预期的那样返回: [ { "a": ..., "b": ..., "c": ... }, { "a": ..., "b": ..., "c": ... } ] 现在我想要相同的结果,但是在输出中只有列a和b。我仍将使用列

我有一个表
t
,其中有一些列
a
b
c
。我使用以下查询将行转换为对象的JSON数组:

SELECT COALESCE(JSON_AGG(t ORDER BY c), '[]'::json)
FROM   t
这将如预期的那样返回:

[
  {
    "a": ...,
    "b": ...,
    "c": ...
  },
  {
    "a": ...,
    "b": ...,
    "c": ...
  }
]
现在我想要相同的结果,但是在输出中只有列
a
b
。我仍将使用列
c
进行订购。我想出的最好办法如下:

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

[
  {
    "a": ...,
    "b": ...
  },
  {
    "a": ...,
    "b": ...
  }
]
虽然这样做很好,但我想知道是否有更优雅的方式来做到这一点。我不得不手动定义JSON属性,这让我很沮丧。当然,我知道我必须枚举列
a
b
,但奇怪的是,我必须复制/粘贴相应的JSON属性名,这与列名完全相同


还有其他方法吗?

您可以使用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 FIDLE。

在子查询或cte中执行排序,然后应用
json\u 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

但这不包括列
c
上的排序。在CTE
tmp
或子查询中简单地按c添加
ORDER是不正确的,因为您需要在外部查询中进行排序。因此,您需要将
c
添加到CTE或子查询中的投影中。但接下来你又回到了原来的问题……为什么在外部查询中需要排序?请看这里:在这种情况下,“异常”是因为LIMIT子句。我不是SQL专家,但我始终理解,子查询/CTE的排序不能保证按照SQL规范保留在外部查询中。我认为这是不对的。据我所知,
orderby
必须在外部查询中完成。您能否给我一个反例,其中此查询会向您返回不同的结果。我尝试了以下测试数据,得到了完全相同的结果:我不是SQL专家,但我始终理解,子查询/CTE的顺序不能保证按照SQL规范保存在外部查询中。因此,从即席小提琴中衍生行为是危险的/棘手的。请参阅更新的答案,了解不依赖子查询顺序的替代解决方案这是一种创造性的构造!但我不认为这是一个理想的解决方案。