次の表があります。
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 に対して、アクティビティが作成されます。
各スケジュールの最新の固有のアクティビティと、その下にあるアクティビティの数を表示する必要があります。
Postgreウィンドウ関数を使用した次のクエリは、その仕事をします。
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 で定義された各パーティションのトップ シェルフ アクティビティが必要です。
クエリを次のように少し変更します。
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;
カウントを除いて、ほぼ望ましい結果が得られます: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)
動作しません。
エラーは
ERROR: column "range" does not exist
LINE 9: count(*) over(partition by range,scheduleid, name)