按天分组聚合

Mar*_*yer 3 sql postgresql json aggregate-functions

log在Postgres数据库中有一个简单的表,看起来像这样(示例简化):

time::timestamptz
action::varchar

time                          | action
2017-10-16 17:14:49.473903-08 | 'some action'
2017-10-16 17:14:49.473903-08 | 'some other action'
2017-10-17 17:14:49.473903-08 | 'some action'
//etc.
Run Code Online (Sandbox Code Playgroud)

有各种各样的行动.我想查询此表以获得每天一行,其中包含每个操作的计数数组.这是我想要的结果:

day            actions
'2017-10-08' | [{"action":"some action", "count":10}, 
             |  {"action":"some other action", "count":20}}]
'2017-10-09' | [{"action":"some action", "count":15}, 
             |  {"action":"some other action", "count":18}}]
Run Code Online (Sandbox Code Playgroud)

我几乎可以用这个:

SELECT day, json_agg(act) as actions
FROM (
    SELECT action, time::date as day,  COUNT(*)
    FROM log_hits
    GROUP BY (action, day)
) act
GROUP BY day
Run Code Online (Sandbox Code Playgroud)

当然,这会导致在actions数组中的每个对象中发生日期...

day           actions
'2017-10-08' | [{"action":"some action", day:"2017-10-08", "count":10}, 
             |  {"action":"some other action",  day:"2017-10-08", "count":20}}]
Run Code Online (Sandbox Code Playgroud)

......这是多余的(可能效率低下).获取按天分组的结果的正确方法是什么,只有当天只在自己的列中发生,而且操作仅聚合当天?

kli*_*lin 5

使用 jsonb_build_object():

WITH log_hits (time, action) AS (
VALUES
    ('2017-10-16 17:14:49.473903-08'::timestamptz, 'some action'),
    ('2017-10-16 17:14:49.473903-08', 'some other action'),
    ('2017-10-17 17:14:49.473903-08', 'some action')
)

SELECT 
    day, 
    json_agg(jsonb_build_object('action', action, 'count', count)) as actions
FROM (
    SELECT action, time::date as day, COUNT(*)
    FROM log_hits
    GROUP BY (action, day)
) act
GROUP BY day;

    day     |                                       actions                                        
------------+--------------------------------------------------------------------------------------
 2017-10-17 | [{"count": 1, "action": "some action"}, {"count": 1, "action": "some other action"}]
 2017-10-18 | [{"count": 1, "action": "some action"}]
(2 rows)
Run Code Online (Sandbox Code Playgroud)