PostgreSQL select 语句到 return 行后 where 条件
PostgreSQL select statement to return rows after where condition
每当“where event = 1”指示的事件发生时,我正在查询 return 接下来 7 天的数据价值。目标是然后按用户 ID 对所有数据进行分组,并在事件发生后对该数据执行聚合函数 - 事件被编码为二进制 [0, 1].
到目前为止,我一直在尝试使用嵌套的 select 语句来构建我想要的数据结构,但是使用 window 函数开始限制我。我现在认为自连接可能更合适,但在构建此类查询时需要帮助。
查询当前首先创建按用户和日期分组的每日聚合值(第 3 级嵌套 select)。然后,第2级对数据“value_x”进行求和,得到用户分组的聚合值。然后,第一级嵌套 select 语句使用 lead 函数获取下一行值并由每个用户分区,当事件 = 1 时充当第二天的值 select。最后,select 语句使用聚合函数计算按用户分组且事件 = 1 的平均值“sum_next_day_value_after_event”。放在一起,其中事件 = 1,查询 returns avg(value_x) 下一行的总数 value_x.
然而,这不符合我的时间规则; “where event = 1”,return 事件发生后接下来 7 天的数据。如果没有 7 天的数据,那么 return 任何数据 <= 7 天。是的,我目前只有一个偏移量为 1 的导联,但您可以再添加 6 个这样的函数来获取接下来的 6 行。但是,lead 函数目前只抓取下一行而不考虑日期。所以从理论上讲,下一行的“value_x”实际上可能距离“event = 1”的位置有 15 天。此外,如下面的数据 table 所示,一个用户每天可能有不止一行。
这是我目前的以下查询:
select
f.user_id
avg(f.sum_next_day_value_after_event) as sum_next_day_values
from (
select
bld.user_id,
lead(bld.value_x, 1) over(partition by bld.user_id order by bld.daily) as sum_next_day_value_after_event
from (
select
l.user_id,
l.daily,
sum(l.value_x) as sum_daily_value_x
from (
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
group by date_part('day', day_ts), user_id, value_x) l
group by l.user_id, l.day_ts
order by l.user_id) bld) f
group by f.user_id
以下是来自 table_1 的数据片段:
user_id
day_ts
value_x
event
50
4/2/21 07:37
25
0
50
4/2/21 07:42
45
0
50
4/2/21 09:14
67
1
50
4/5/21 10:09
8
0
50
4/5/21 10:24
75
0
50
4/8/21 11:08
34
0
50
4/15/21 13:09
32
1
50
4/16/21 14:23
12
0
50
4/29/21 14:34
90
0
55
4/4/21 15:31
12
0
55
4/5/21 15:23
34
0
55
4/17/21 18:58
32
1
55
4/17/21 19:00
66
1
55
4/18/21 19:57
54
0
55
4/23/21 20:02
34
0
55
4/29/21 20:39
57
0
55
4/30/21 21:46
43
0
技术细节:
PostgreSQL,EDB 支持,版本 = 14.1
pgAdmin4,版本 5.7
感谢您的帮助!
"查询当前首先创建每日聚合值"
我在您的第一个查询中没有看到任何聚合函数,因此 GROUP BY
子句没有用。
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
group by date_part('day', day_ts), user_id, value_x
可以简化为
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
这又没有提供真正的附加值,因此可以删除第一个查询,第二个查询将变为:
select user_id
, date_part('day', day_ts) as daily
, sum(value_x) as sum_daily_value_x
from table_1
group by user_id, date_part('day', day_ts)
也可以在此步骤删除 order by user_id
子句。
现在如果你想计算事件发生后7天内sum_daily_value_x的平均值(我指的是avg()
函数),您可以将 avg()
用作 window 函数,您可以将其限制为事件发生后 7 天的时间段:
select f.user_id
, avg(f.sum_daily_value_x) over (order by f.daily range between current row and '7 days' following) as sum_next_day_values
from (
select user_id
, date_part('day', day_ts) as daily
, sum(value_x) as sum_daily_value_x
from table_1
group by user_id, date_part('day', day_ts)
) AS f
group by f.user_id
window 函数中的 partition by f.user_id
子句没有用,因为行在 window 之前已经按 f.user_id 分组=] 函数被应用。
您可以将 avg()
window 函数替换为任何其他函数,例如 sum()
可以更适合别名 sum_next_day_values
每当“where event = 1”指示的事件发生时,我正在查询 return 接下来 7 天的数据价值。目标是然后按用户 ID 对所有数据进行分组,并在事件发生后对该数据执行聚合函数 - 事件被编码为二进制 [0, 1].
到目前为止,我一直在尝试使用嵌套的 select 语句来构建我想要的数据结构,但是使用 window 函数开始限制我。我现在认为自连接可能更合适,但在构建此类查询时需要帮助。
查询当前首先创建按用户和日期分组的每日聚合值(第 3 级嵌套 select)。然后,第2级对数据“value_x”进行求和,得到用户分组的聚合值。然后,第一级嵌套 select 语句使用 lead 函数获取下一行值并由每个用户分区,当事件 = 1 时充当第二天的值 select。最后,select 语句使用聚合函数计算按用户分组且事件 = 1 的平均值“sum_next_day_value_after_event”。放在一起,其中事件 = 1,查询 returns avg(value_x) 下一行的总数 value_x.
然而,这不符合我的时间规则; “where event = 1”,return 事件发生后接下来 7 天的数据。如果没有 7 天的数据,那么 return 任何数据 <= 7 天。是的,我目前只有一个偏移量为 1 的导联,但您可以再添加 6 个这样的函数来获取接下来的 6 行。但是,lead 函数目前只抓取下一行而不考虑日期。所以从理论上讲,下一行的“value_x”实际上可能距离“event = 1”的位置有 15 天。此外,如下面的数据 table 所示,一个用户每天可能有不止一行。
这是我目前的以下查询:
select
f.user_id
avg(f.sum_next_day_value_after_event) as sum_next_day_values
from (
select
bld.user_id,
lead(bld.value_x, 1) over(partition by bld.user_id order by bld.daily) as sum_next_day_value_after_event
from (
select
l.user_id,
l.daily,
sum(l.value_x) as sum_daily_value_x
from (
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
group by date_part('day', day_ts), user_id, value_x) l
group by l.user_id, l.day_ts
order by l.user_id) bld) f
group by f.user_id
以下是来自 table_1 的数据片段:
user_id | day_ts | value_x | event |
---|---|---|---|
50 | 4/2/21 07:37 | 25 | 0 |
50 | 4/2/21 07:42 | 45 | 0 |
50 | 4/2/21 09:14 | 67 | 1 |
50 | 4/5/21 10:09 | 8 | 0 |
50 | 4/5/21 10:24 | 75 | 0 |
50 | 4/8/21 11:08 | 34 | 0 |
50 | 4/15/21 13:09 | 32 | 1 |
50 | 4/16/21 14:23 | 12 | 0 |
50 | 4/29/21 14:34 | 90 | 0 |
55 | 4/4/21 15:31 | 12 | 0 |
55 | 4/5/21 15:23 | 34 | 0 |
55 | 4/17/21 18:58 | 32 | 1 |
55 | 4/17/21 19:00 | 66 | 1 |
55 | 4/18/21 19:57 | 54 | 0 |
55 | 4/23/21 20:02 | 34 | 0 |
55 | 4/29/21 20:39 | 57 | 0 |
55 | 4/30/21 21:46 | 43 | 0 |
技术细节:
PostgreSQL,EDB 支持,版本 = 14.1
pgAdmin4,版本 5.7
感谢您的帮助!
"查询当前首先创建每日聚合值"
我在您的第一个查询中没有看到任何聚合函数,因此 GROUP BY
子句没有用。
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
group by date_part('day', day_ts), user_id, value_x
可以简化为
select
user_id, value_x, date_part('day', day_ts) as daily
from table_1
这又没有提供真正的附加值,因此可以删除第一个查询,第二个查询将变为:
select user_id
, date_part('day', day_ts) as daily
, sum(value_x) as sum_daily_value_x
from table_1
group by user_id, date_part('day', day_ts)
也可以在此步骤删除 order by user_id
子句。
现在如果你想计算事件发生后7天内sum_daily_value_x的平均值(我指的是avg()
函数),您可以将 avg()
用作 window 函数,您可以将其限制为事件发生后 7 天的时间段:
select f.user_id
, avg(f.sum_daily_value_x) over (order by f.daily range between current row and '7 days' following) as sum_next_day_values
from (
select user_id
, date_part('day', day_ts) as daily
, sum(value_x) as sum_daily_value_x
from table_1
group by user_id, date_part('day', day_ts)
) AS f
group by f.user_id
window 函数中的 partition by f.user_id
子句没有用,因为行在 window 之前已经按 f.user_id 分组=] 函数被应用。
您可以将 avg()
window 函数替换为任何其他函数,例如 sum()
可以更适合别名 sum_next_day_values