LINUX.ORG.RU

PostgreSQL, ограничение возвращаемого набора данных

 ,


1

2

Возможно ли средствами базы ограничить выборку? То есть клиент дает запрос

select x,y,z from XYZ;
, если записей больше чем xxx откинуть лишние, суммировать, вычислить среднее и т.д.То есть вызвать функцию самой базы.

Это возможно сделать на клиенте, но, не хотелось бы его трогать.

★★
Ответ на: комментарий от at

на самом деле, это вторая ссылка в гугле по запросу «postgresql statistics», сразу же после аггрегатных функций (http://www.postgresql.org/docs/8.3/static/functions-aggregate.html)

то есть я просто рассказал тебе результаты гугления, может там чушь :) Но выглядит как правда

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
select x,y,z from XYZ limit xxx;
anonymous
()
Ответ на: комментарий от stevejobs

По ссылке я, пока, ничего не понял. PL/R вижу первый раз. Я могу написать функцию на стороне сервера, не знаю, возможно ли вызвать её select-ом

at ★★
() автор топика
Ответ на: комментарий от Attila

Ты не понял. Мне нужно: а) если число записей меньше xxx отдать их как есть. б) если больше, объединить их, а не просто срезать лишнее

at ★★
() автор топика
Ответ на: комментарий от stevejobs

Спасибо! По крайней мере это направление куда стоит копять

at ★★
() автор топика
Ответ на: комментарий от Attila

В качестве примера (никакого отношения к реальной задаче не имеет).

Есть таблица с данными по температуре каждые 5 мин, то есть запись вида дата/время,температура. Если сделать выборку, например, за год будет много данных. Мне нужно не откинуть лишние, а выдать среднее за час, день и т.д.

at ★★
() автор топика
Ответ на: комментарий от at

Сейчас структура такая, я понял:
CREATE TABLE xyz
(
ts timestamp NOT NULL,
temp_deg_c real NOT NULL
);

Ну так добавьте еще несколько полей (назвал условно):
hour int,
month int,
year int

Если тот, кто пишет в таблицу ничего о них не знает
и возможность научить отсуствует,
запускайте каждую ночь из-под крона скрипт, к-рый
распишет/проапдейтит поля hour, month, year
на основании имеющегося значения ts для тех записей,
у к-рых hour,month,year IS NULL на момент запуска

Т.о., заплАтите лишней тройкой полей за удобство выборки.

Если организовать без таких полей, то я не очень, честно говоря,
представляю как вы будете определять по какому интервалу
какая запись из выборки (среднее или что там у вас еще будет)
рассчитана, имея результат запроса.

braindef
()
Ответ на: комментарий от unC0Rr

А как получить средние часовые значения, скажем, за последние полтора месяца?
А среднесуточные за тот же период?

braindef
()
Ответ на: комментарий от unC0Rr

Да, это так! Хорошая функция!

Однако, для получения, к примеру, среднечасовых
за период с 8:00 до 16:00 за январи 3 последних лет
нужно будет встать на уши.

Я бы заплатил «лишними» полями, пожалуй.

braindef
()
Ответ на: комментарий от braindef

generate_series(date_trunc('year', CURRENT_DATE - interval '2 years'), date_trunc('year', CURRENT_DATE), '1 year') для получения серии из начал трёх последних лет, EXTRACT(hour FROM time) для получения часа из времени, ну в целом что-то такое получится:

SELECT avg(td.temperature) FROM 
  (SELECT generate_series(date_trunc('year', CURRENT_DATE - interval '3 years'), date_trunc('year', CURRENT_DATE - interval '1 year'), '1 year') as y) as years
  JOIN tempdata as td ON (td.time BETWEEN years.y AND years.y + interval '1 month' AND EXTRACT(hour FROM td.time) BETWEEN 8 AND 15)
GROUP BY date_trunc('hour', td.time)

unC0Rr ★★★★★
()
Последнее исправление: unC0Rr (всего исправлений: 1)
Ответ на: комментарий от braindef

«Лишние» поля все не предусмотришь. А вдруг понадобится то же самое, но по неделям или по дням недели, к примеру? Всё равно есть функции, которые позволят провести любую необходимую манипуляцию с датой, так что достаточно указания даты.

unC0Rr ★★★★★
()
Последнее исправление: unC0Rr (всего исправлений: 2)
Ответ на: комментарий от braindef

Структура таблицы сложнее, я пока сделал пару доп. таблиц, куда скидываю статистику. То есть софт, который опрашивает сенсоры делает свою, я добавляю пару дополнительных. С этим проблем нет.

Единственное, мне хотелось бы как можно меньше модифицировать клиент (это что то страшное, изначально написанное на php3), то есть всё, что возможно сделать в самой базе или на сервере. Пока думаю на клиенте заменить

select x,y,z from tablename ...
на
select func(...)
, а остальное делать на сервере.

at ★★
() автор топика
Ответ на: комментарий от unC0Rr

Пока я получаю из даты количество секунд (то есть юникстайм) как число, делю его на количество сек. в часе и т.д. и группирую по этому признаку. ИМХО так проще

at ★★
() автор топика
Ответ на: комментарий от unC0Rr

Месье знает толк в стоянии на ушах!! :)))
Вы сделали мое утро, я радостно смеялся!

А если все то же самое, но только для четных часов? ;)

braindef
()
Ответ на: комментарий от unC0Rr

Вопросов нет, всего не предусмотреть.
Баланс между кол-вом «лишних» полей и
временем/памятью выполнения запроса
надо определять исходя таки из задачи.
Но в общем виде, конечно, хватит и timestamp'а.

braindef
()
Ответ на: комментарий от braindef

А если все то же самое, но только для четных часов? ;)

Ровно так же, как с отдельным полем hour, просто заменяешь его везде на extract(hour from time)

unC0Rr ★★★★★
()
Ответ на: комментарий от braindef

Это первое, что мне пришло в голову. Надо будет попробовать с date_trunc

at ★★
() автор топика
Ответ на: комментарий от at

Пока я получаю из даты количество секунд (то есть юникстайм) как число, делю его на количество сек. в часе и т.д. и группирую по этому признаку. ИМХО так проще

Чем не устраивают встроенные функции для работы с временем?

AnDoR ★★★★★
()
Ответ на: комментарий от AnDoR

Мне показалось, что с числами работать удобней. Естественно, есть некоторые ограничения, например я считаю что месяц это всегда 30 дней, но для данной задачи это не имеет большого значения.

at ★★
() автор топика
Ответ на: комментарий от at

Мне показалось, что с числами работать удобней. Естественно, есть некоторые ограничения, например я считаю что месяц это всегда 30 дней, но для данной задачи это не имеет большого значения.

Тебе показалось.

AnDoR ★★★★★
()
Ответ на: комментарий от AnDoR

Я же написал

Это первое, что мне пришло в голову. Надо будет попробовать с date_trunc

at ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.