我有一张桌子:
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想要的结果,除了count: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行:count(*)over(按范围划分,scheduleid,name)
答案 0 :(得分:2)
将count()
(和DISTINCT ON
)移至新查询:
WITH top_activities AS (
SELECT
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
FROM activity ORDER BY range, scheduleid, name,duedate desc
),
top_activities_with_count as (
SELECT DISTINCT ON (range, scheduleid, name)
*, count(*) over(partition by range, scheduleid, name)
FROM top_activities
)
SELECT * FROM top_activities_with_count ORDER BY scheduleid;