Агрегация + последний и первый -> убыточный ордер - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь выбрать данные в течение 15 минут.Основные групповые швы работают близко, как и ожидалось, однако я теряю порядок в каждой 15-минутной группе.Причина в том, что, например: Для 4 точек, где time_stamp находится в диапазоне 0-14 минут -> "floor (EXTRACT (минута FROM time_stamp) / 15) AS четверть"), будет возвращено значение "0" (как и ожидалось).Тогда ORDER BY "четверть" 4 строки с "четвертью" == "0", из которых выбираются последнее и первое значенияЭто приводит к тому, что я не могу гарантировать сортировку по отметке времени.

SELECT
    first(value) as first_value,
    last(value) as last_value,
    CAST(EXTRACT(year FROM time_stamp) AS INTEGER) AS year,
    CAST(EXTRACT(month FROM time_stamp) AS INTEGER) AS month,
    CAST(EXTRACT(day FROM time_stamp) AS INTEGER) AS day,
    CAST(EXTRACT(hour FROM time_stamp) AS INTEGER) AS hour,
    floor(EXTRACT(minute FROM time_stamp) / 15) AS quarter,
FROM
    my_table
GROUP BY
    year,
    month,
    day,
    hour,
    quarter,
ORDER BY
    year,
    month,
    day,
    hour,
    quarter

Ниже приведен пример таблицы:

CREATE TABLE my_table (
    id integer NOT NULL,
    time_stamp timestamp without time zone NOT NULL,
    value double precision NOT NULL,
);


CREATE SEQUENCE my_table_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;


ALTER TABLE ONLY my_table ALTER COLUMN id SET DEFAULT nextval('my_table_id_seq'::regclass);


ALTER TABLE ONLY my_table
    ADD CONSTRAINT my_table_pkey PRIMARY KEY (id);


CREATE INDEX ix_my_table_time_stamp ON my_table USING btree (time_stamp);

Я также удалил «первую» и «последнюю» функцию из запроса, чтобы уведомить, что сортировка действительно отсутствует.

Любой совет, как продолжать сортировку в течение каждого 15-минутного шага?

1 Ответ

0 голосов
/ 11 июня 2018

Стандартных агрегатных функций нет first() и last(), вы, вероятно, имеете в виду определенные пользователем агрегаты, такие как:

create or replace function first_agg(anyelement, anyelement)
returns anyelement language sql immutable strict
as $$ select $1; $$;

create or replace function last_agg(anyelement, anyelement)
returns anyelement language sql immutable strict
as $$ select $2; $$;

create aggregate first(anyelement) (
    sfunc = first_agg,
    stype = anyelement
);

create aggregate last(anyelement) (
    sfunc = last_agg,
    stype = anyelement
);

Используйте order by в аггегатах, см. 4.2.7.Совокупные выражения в документации.

SELECT
    first(value order by time_stamp) as first_value,
    last(value order by time_stamp) as last_value,
    CAST(EXTRACT(year FROM time_stamp) AS INTEGER) AS year,
    CAST(EXTRACT(month FROM time_stamp) AS INTEGER) AS month,
    CAST(EXTRACT(day FROM time_stamp) AS INTEGER) AS day,
    CAST(EXTRACT(hour FROM time_stamp) AS INTEGER) AS hour,
    floor(EXTRACT(minute FROM time_stamp) / 15) AS quarter
FROM
    my_table
GROUP BY
    year,
    month,
    day,
    hour,
    quarter
ORDER BY
    year,
    month,
    day,
    hour,
    quarter

DbFiddle.

...