【问题标题】:Sort Group by query based on JSONB first values根据 JSONB 第一个值按查询排序组
【发布时间】:2021-04-01 06:38:05
【问题描述】:

我正在使用 PostgreSQL,我有以下 SQL 查询

    WITH A AS
(
    SELECT *,
    jsonb_array_elements(event_days) as event_days_arr
    FROM event
)
SELECT event_id::int, 
    MAX(area_id)::int AS area_id, 
    array_agg(event_days_arr) as event_days
FROM A 
WHERE
    event_days_arr->>'start_datetime' >= '2020-12-22' AND
    event_days_arr->>'end_datetime' < '2020-12-22T19:00:00'
GROUP BY event_id, event_alias
ORDER BY 
    (event_days_arr->0->>'start_datetime'),
    (event_days_arr->0->>'end_datetime');

如您所见,我有一个名为“event_days”的数组,我想根据该数组第一个元素中的键对结果进行排序

由于某种原因,我有以下错误:

ERROR:  column "a.event_days_arr" must appear in the GROUP BY clause or be used in an aggregate function

我已尝试使用 event_days、event_days_arr,但我无法根据每行的 JSONB 数组的第一个元素对查询结果进行排序

谁能帮我对这个查询的结果进行排序?

【问题讨论】:

    标签: sql arrays postgresql jsonb unnest


    【解决方案1】:

    我认为您想按 event_days 的第一个元素而不是 event_days_arr 的第一个元素进行分组。

    这不就行了吗?

    WITH A AS (
        SELECT *, jsonb_array_elements(event_days) as event_days_arr
        FROM event
    )
    SELECT event_id::int, 
        MAX(area_id::int) AS area_id, 
        ARRAY_AGG(event_days_arr) as event_days
    FROM A 
    WHERE
        event_days_arr ->> 'start_datetime' >= '2020-12-22' AND
        event_days_arr ->> 'end_datetime'   <  '2020-12-22T19:00:00'
    GROUP BY event_id, event_alias
    ORDER BY 
        event_days -> 0 ->> 'start_datetime',
        event_days -> 0 ->> 'end_datetime';
    

    Postgres 应该能够识别order by 列依赖于event_id。如果没有,那么您需要将列添加到 group by 子句:

    GROUP BY event_id, event_alias, event_days -> 0 ->> 'start_datetime', event_days -> 0 ->> 'end_datetime'
    

    【讨论】:

    • 我试图做的是按 event_id 和 event_alias 分组,就像我在做的那样。尝试按日期时间数组进行分组....听起来我很奇怪,但感谢您的关注
    • 还有一件事,我发现如果你使用“array_agg”函数,并且你尝试按它的元素排序,即使group by让你这样做,你也需要先访问event_days 的元素如:“event_days[0]->>'start_datetime'”,不像我之前所说的“event_days -> 0 ->> 'start_datetime'”
    【解决方案2】:

    将时间范围的WHERE条件移到公用表表达式中,只要在FROM子句中使用集合返回函数就可以完成(应该使用的地方):

    外部聚合也应该使用 jsonb_agg() 而不是 array_agg() 来完成,因为 -&gt; 运算符仅用于 JSON 数组,而不是原生数组。

    列别名只能在 ORDER BY 部分中“按原样”使用。如果要使用表达式,则需要第二级,例如使用派生表或 CTE:

    WITH A AS
    (
      SELECT *
      FROM event
        cross join jsonb_array_elements(event_days) as arr(event_day)
      WHERE arr.event_day ->> 'start_datetime' >= '2020-12-22' 
        AND arr.event_day ->> 'end_datetime' < '2020-12-22T19:00:00'
    )
    SELECT * 
    FROM (
      SELECT event_id::int, 
             MAX(area_id)::int AS area_id, 
             jsonb_agg(event_day) as event_days
      FROM A 
      GROUP BY event_id, event_alias
    ) t
    ORDER BY event_days -> 0 ->> 'start_datetime',
             event_days -> 0 ->>'end_datetime'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 2018-09-27
      相关资源
      最近更新 更多