窗口函数中的 RANGE 子句错误

sql*_*foo 5 postgresql window-functions postgresql-9.3

我正在尝试RANGE在窗口函数中使用 postgres子句将窗口动态设置为过去 4 周,不包括当前日期。这是我的尝试:

SELECT date("aa0"."created_at") AS "Day of Created At",
       "aa0"."user_id" AS "User Id",
       count (*) activities_today,
       count(*) over (PARTITION BY "aa0"."user_id"
                      ORDER BY date("aa0"."created_at") ASC
                      RANGE BETWEEN date("aa0"."created_at" - interval '4 weeks')
                                    AND 
                                    date("aa0"."created_at" - interval '1 day')
                ) active_days_past_4_weeks
FROM "public"."activity_activity" AS "aa0"
GROUP BY date("aa0"."created_at"), "aa0"."user_id" 
ORDER BY "Day of Created At" ASC LIMIT 1000;
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误:

ERROR: syntax error at or near ")" Position: 459
Run Code Online (Sandbox Code Playgroud)

如果我使用ROWS而不是RANGE它有效,但这不是正确的逻辑,因为不能保证每天都会有一行:

SELECT date("aa0"."created_at") AS "Day of Created At",
       "aa0"."user_id" AS "User Id",
       count(*) activities_today,
       count(*) over (PARTITION BY "aa0"."user_id"
                      ORDER BY date("aa0"."created_at") ASC
                      ROWS BETWEEN 28 PRECEEDING AND 1 PRECEEDING
                ) active_days_past_4_weeks
FROM "public"."activity_activity" AS "aa0"
GROUP BY date("aa0"."created_at"), "aa0"."user_id" 
ORDER BY "Day of Created At" ASC LIMIT 1000;
Run Code Online (Sandbox Code Playgroud)

架构:

CREATE TABLE activity_activity (
  user_id int,
  created_at timestamp
)
Run Code Online (Sandbox Code Playgroud)

版本:

select version()

PostgreSQL 9.3.4 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-16ubuntu6) 4.8.2, 64-bit
Run Code Online (Sandbox Code Playgroud)

Cra*_*ger 7

PostgreSQL 尚不支持该RANGE子句。因此,即使您的语法正确,它也会失败:

regress=> SELECT row_number() OVER (RANGE BETWEEN CURRENT ROW AND 42 FOLLOWING);
ERROR:  RANGE FOLLOWING is only supported with UNBOUNDED
LINE 1: SELECT row_number() OVER (RANGE BETWEEN CURRENT ROW AND 42 F...
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您可以执行左外连接,generate_series(first_day, last_day, INTERVAL '1' DAY)然后使用ROWS基于窗口的窗口。这样每一天都存在一行。它的效率要低得多,但除非您想深入了解 PostgreSQL 的源代码,否则它可能是唯一的选择。