如何将行分组到一个数组[PostgreSQL]

时间:2018-01-23 04:43:49

标签: postgresql

表A:

date_time                     amount    note
2016-03-01 01:00.00.000000    100       "hi"
2016-03-01 02:00.00.000000    5         "hello"
2016-03-01 03:00.00.000000    2         "foo"
2016-04-01 00:00.00.000000    60        "bar"

我需要像这样输出最终表:

ProcessedTable

grouped_date_time     row          total
2016-03-01            RowA         107
2016-04-01            RowB         60

RowA是第一组中所有行的JSON对象数组:

[
  { date_time:2016-03-01 01:00.00.000000, amount:100, note:"hi"}, 
  { date_time:2016-03-01 02:00.00.000000, amount:5, note:"hello"}, 
  { date_time:2016-03-01 03:00.00.000000, amount:2, note:"foo"}
]

RowB是第一组中所有行的JSON对象数组:

[
  { date_time:2016-04-01 00:00.00.000000, amount:60, note:"bar"} 
]

目前我有这样的查询

SELECT date_trunc('day', date_time), array_agg(amount)
    FROM table_a
GROUP BY date_trunc('day', date_time)

我不确定要为array_agg(amount)提取什么来将整个JSON对象作为列提取出来,以及每个组的总量。

2 个答案:

答案 0 :(得分:0)

以下内容应该有效:

SELECT DATE_TRUNC('day', date_time), 
    JSON_AGG(ROW_TO_JSON(table_a)) AS row, 
    SUM(amount) AS total
FROM table_a GROUP BY DATE_TRUNC('day', date_time);

ROW_TO_JSON(table_a)将SQL行转换为JSON对象时,JSON_AGG会将所有对象收集到JSON数组中。

输出(使用JSONB_PRETTY):

     date_trunc      |                    row                     | total 
---------------------+--------------------------------------------+-------
 2016-03-01 00:00:00 | [                                         +|   107
                     |     {                                     +| 
                     |         "note": "hi",                     +| 
                     |         "amount": 100,                    +| 
                     |         "date_time": "2016-03-01T01:00:00"+| 
                     |     },                                    +| 
                     |     {                                     +| 
                     |         "note": "hello",                  +| 
                     |         "amount": 5,                      +| 
                     |         "date_time": "2016-03-01T02:00:00"+| 
                     |     },                                    +| 
                     |     {                                     +| 
                     |         "note": "foo",                    +| 
                     |         "amount": 2,                      +| 
                     |         "date_time": "2016-03-01T03:00:00"+| 
                     |     }                                     +| 
                     | ]                                          | 
 2016-04-01 00:00:00 | [                                         +|    60
                     |     {                                     +| 
                     |         "note": "bar",                    +| 
                     |         "amount": 60,                     +| 
                     |         "date_time": "2016-04-01T00:00:00"+| 
                     |     }                                     +| 
                     | ]                                          | 

修改:删除ROW_TO_JSON可以进一步简化查询:

SELECT DATE_TRUNC('day', date_time), JSON_AGG(t) AS row, SUM(amount) AS total
FROM table_a t GROUP BY DATE_TRUNC('day', date_time);

答案 1 :(得分:0)

您可以在转到row_to_json之前选择整行,使用ctegroup by

with t1 as(
select date_time as dt, amount,
   (select row_to_json(this_row) 
      from (select t.date_time, t.amount, t.note) as this_row) as rowdict
from table_a as t
)
select date_trunc('day', dt), array_agg(rowdict) as row, sum(amount) as total
from t1
group by 1;