如何从内部查询访问 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;
在您的原始文件中,相关子查询 引用了 input 列 mainEvent.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
:
我正在 运行 处理一个有趣的案例,其中内部查询无法访问 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;
在您的原始文件中,相关子查询 引用了 input 列 mainEvent.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
: