我有一个下表:
Table "public.activity"
Column | Type | Modifiers
------------+-----------------------------+-------------------------------------------------------
id | integer | not null default nextval('activity_id_seq'::regclass)
scheduleid | integer |
name | text |
duedate | timestamp without time zone |
Indexes:
"activity_pkey" PRIMARY KEY, btree (id)
使用以下数据:
id | scheduleid | name | duedate
----+------------+----------+----------------------------
1 | 1 | ACT1 | 2015-09-21 13:34:53.738449
2 | 1 | ACT1 | 2015-09-20 13:35:02.770369
3 | 1 | ACT1 | 2015-09-19 13:35:07.650204
4 | 1 | ACT1 | 2015-09-18 13:35:11.930225
5 | 1 | ACT1.0.0 | 2015-09-17 13:35:48.033791
6 | 1 | ACT1.0.0 | 2015-09-16 13:35:51.55382
7 | 2 | ACT2.0.0 | 2015-09-21 13:36:56.42534
8 | 2 | ACT2.0.0 | 2015-09-28 13:37:21.065071
9 | 2 | ACT2.0.0 | 2015-10-05 13:37:26.753227
10 | 2 | ACT2.0.0 | 2015-10-12 13:37:30.656846
11 | 2 | ACT2.0.0 | 2015-10-19 13:37:34.54473
12 | 2 | ACT2.0.0 | 2015-10-26 13:37:38.192843
(12 rows)
对于每个 scheduleId,我们都创建了活动。
我需要显示每个时间表的最新独特活动以及包含在其下的活动计数。
使用 Postgres 窗口函数进行以下查询即可完成工作。
WITH TOP_ACTIVITIES AS (
SELECT DISTINCT ON (scheduleid, name)
id, scheduleid, name, duedate,
count(*) over(partition by scheduleid, name) as clubbedcount
from activity ORDER BY scheduleid, name, duedate desc
)
select * from TOP_ACTIVITIES;
结果如下:
id | scheduleid | name | duedate | clubbedcount
----+------------+----------+----------------------------+--------------
1 | 1 | ACT1 | 2015-09-21 13:34:53.738449 | 4
5 | 1 | ACT1.0.0 | 2015-09-17 13:35:48.033791 | 2
12 | 2 | ACT2.0.0 | 2015-10-26 13:37:38.192843 | 6
到目前为止一切顺利:P
现在有个小转折是,我们也需要按它们的 rangeTag 对活动进行分组
Eg: Todays date being 21-Sep-2015,
activities with duedate <= now() --> club under TODAY tag
activities with duedate <= now() + 7 days --> club under THIS WEEK tag
activities with duedate <= now() + 1 month --> club under THIS MONTH tag
ELSE --> club under FUTURE tag
因此,我们需要 1. 由 rangeTag、scheduleid 和 name 定义的每个分区的顶级活动 2. 活动计数,将每个分区整理到顶级活动中。
稍微修改我的查询:
WITH TOP_ACTIVITIES AS (
SELECT DISTINCT ON (range, scheduleid, name)
id, scheduleid, name, duedate,
CASE WHEN duedate < now() THEN 'TODAY'
WHEN duedate < now() + interval '7 days' THEN 'THIS WEEK'
WHEN duedate < now() + interval '1 month' THEN 'THIS MONTH'
ELSE 'FUTURE'
END AS range,
count(*) over(partition by scheduleid, name)
from activity ORDER BY range, scheduleid, name,duedate desc
)
select * from TOP_ACTIVITIES ORDER BY scheduleid;
给了我 NEAR 想要的结果,除了计数:P
id | scheduleid | name | duedate | range | count
----+------------+----------+----------------------------+------------+-------
1 | 1 | ACT1 | 2015-09-21 13:34:53.738449 | TODAY | 4
5 | 1 | ACT1.0.0 | 2015-09-17 13:35:48.033791 | TODAY | 2
12 | 2 | ACT2.0.0 | 2015-10-26 13:37:38.192843 | FUTURE | 6
11 | 2 | ACT2.0.0 | 2015-10-19 13:37:34.54473 | THIS MONTH | 6
8 | 2 | ACT2.0.0 | 2015-09-28 13:37:21.065071 | THIS WEEK | 6
7 | 2 | ACT2.0.0 | 2015-09-21 13:36:56.42534 | TODAY | 6
我也需要按“范围”划分的计数。
但是,更换
count(*) over(partition by scheduleid, name)
和
count(*) over(partition by range, scheduleid, name)
不起作用。
错误是
错误:列“范围”不存在
第 9 行:计数(*)超过(按范围、计划 ID、名称分区)