如何从内部查询访问 GROUP BY 中的截断值?

How to access truncated value in GROUP BY from inner query?

我正在 运行 处理一个有趣的案例,其中内部查询无法访问 GROUP BY 子句中使用的 t运行cated 值。如何从父查询访问 t运行c-modified GROUP BY 子句?

这是一个删节版:

SELECT
date_trunc('week', mainEvent.timestamp::date + 1)::date -1 AS weekly,
   (
        SELECT sum(p.value)
        FROM myschema.purchase as p
        WHERE p.non_unique_id = mainEvent.non_unique_id
              AND date_trunc('week', p.timestamp::date + 1)::date -1 
                = date_trunc('week', mainEvent.timestamp::date + 1)
        GROUP BY (date_trunc('week', p.timestamp::date + 1)::date -1)::date
   ) as percent_of_week
FROM myschema.event as mainEvent
WHERE mainEvent.internal_feed_name IS NOT NULL
GROUP BY weekly, mainEvent.non_unique_id;

这会产生错误 subquery uses ungrouped column "mainevent.timestamp" from outer query Position: 1587

我尝试将外部 GROUP BY 子句更改为:

GROUP BY date_trunc('week', mainEvent.timestamp::date + 1)::date -1, mainEvent.non_unique_id

但它returns同样的错误。但是,如果我从外部 GROUP BY

中删除 trunc
GROUP BY mainEvent.timestamp

引用外部查询的GROUP BY“有效”。这让我认为这在原则上是有效的,但 PostGres 不理解变异的分组。也许有一些语法糖可以使它起作用?有没有办法通过创建临时 table 来做到这一点?我还尝试了 window 函数 sum(over) 等的一些变体,但我仍然 运行 遇到引用父分组列的问题......我不想按原始时间戳分组,我想每周分组。

目标:我需要在执行伪代码的地方聚合数据:(x / sum(x) in week) as percent_of_week 对每周总计求和。

所以一些数学除以小组的总和。实际上,子查询有一个与每个唯一值相关联的分子(为简洁起见此处省略),除以主要组 week 的总和,这就是为什么简单地连接不起作用的原因。我的架构中也没有外键(原始分析数据)。

多个问题。考虑 LEFT JOIN LATERAL 而不是:

SELECT *
FROM  (
   SELECT non_unique_id
        , date_trunc('week', timestamp + interval '1 day')::date - 1 AS weekly
   FROM   myschema.event
   WHERE  internal_feed_name IS NOT NULL
   GROUP  BY 1, 2
   ) main_event
LEFT   JOIN LATERAL (
   SELECT sum(p.value) AS sum_value
   FROM   myschema.purchase p
   WHERE  p.non_unique_id = main_event.non_unique_id
   AND    p.timestamp >= main_event.weekly
   AND    p.timestamp <  main_event.weekly + 7
   ) p ON true;

在您的原始文件中,相关子查询 引用了 inputmainEvent.timestamp,即 ungrouped,因为这在逻辑上发生在聚合之前。这是您报告错误消息的直接原因。

您无法通过引用 output 列名称 weekly 来解决此问题,因为它在相关子查询中是不可见的。您必须重写查询:首先聚合,然后加入tablepurchase.

我建议使用更简洁的 LEFT JOIN LATERAL 而不是相关子查询(尽管现在可以在下一个查询级别上实现)。

不需要在子查询中添加另一个 GROUP BY,因为它在任何情况下都应该准确地生成 one 行。删除它即可。

我通过使用位置引用而不是重复 SELECT 列表中的表达式来缩短代码。那是可选的。参见:

  • When can we use an identifier number instead of its name in PostgreSQL?

使用“可搜索”表达式通常效率更高:

WHERE    p.timestamp >= main_event.weekly
AND      p.timestamp <  main_event.weekly + 7

假设您希望一周从 weekly 开始。否则相应地移动两个边界。

关于LATERAL