PostgreSQL: оконные функции, использующие псевдоним столбца

У меня есть следующая таблица:

                                    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

Небольшой поворот состоит в том, что нам нужно сгруппировать действия по их диапазону.

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;

дает мне РЯДОМ желаемый результат, кроме подсчета: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: счетчик (*) более (разделение по диапазону, расписанию, имени)

1 ответ

Переехать 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;
Другие вопросы по тегам