powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с запросом.
8 сообщений из 8, страница 1 из 1
Помогите с запросом.
    #33956712
puzzle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
существует таблица (recid, tdate, value) порядка 50.000.000 записей.
В ней данные разбиты по дня, в каждом дне порядка 100.000.
необходимо выбрать из каждого дня МАКС и МИН, не включая первую и последнюю запись (по recid).
(если запросом выбирать первую и последнюю для кадого дня записи то получится очень долго), может есть какой-нить способ или другое решение.

Заренне благодарен, Павел.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33957192
ChameLe0n
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
IMHO объем данных слишком большой для быстрой выборки.
Как варианты:
1) Попробовать партиционирование, скажем хотябы по номеру месяца.
2) Сделать cron ночью чтобы он расчитывал эти параметры только за прошлые сутки и записывал их в отдельную таблицу. Ну и соответсвенно готовые данные забирать уже оттуда.
3) Есть ли необходимость хранить данные за 500 дней? Если особой нужды нет - может быть тогда сделать архивную таблицу и иногда туда скидывать ненужные данные.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33957222
nig_AM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
тут скорее на запросом а архитектурой попахивает.
дай более точную формулировку задачи- т.е. тебе нужно каждый день в начале работы получать обработку ТОЛЬКО ПРЕДЫДУЩЕГО ДНЯ или нужно иметь возможность постоянно выполнять обработки по всем дням сразу
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33957517
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Необходимы два индекса: dv (tdate, value), di (tdate, recid).

1) Получить список дат, присутствующих в таблице.

while ( $DATE = "select tdate from t where tdate>$DATE order by tdate limit 1" ) { -- быстро с использованием индекса dv или di
-- тело цикла
}

2) В теле цикле для каждой даты выполнить:

2.1) Найти первую и последнюю записи по rec_id:

$ID_FIRST = "select recid from t where tdate=$DATE order by recid limit 1" -- быстро с использованием индекса di
$ID_LAST = "select recid from t where tdate=$DATE order by recid desc limit 1"

2.2) Выбрать min(value), max(value) кроме $ID_FIRST, $ID_LAST:

$VAL_MIN = "select value from t where tdate=$DATE and recid not in ( $ID_FIRST, $ID_LAST ) order by value limit 1" -- быстро с использованием индекса dv
$VAL_MAX = "select value from t where tdate=$DATE and recid not in ( $ID_FIRST, $ID_LAST ) order by value desc limit 1"

2.3) Возвратить $DATE, $VAL_MIN, $VAL_MAX.
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33957647
alex_sm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
попробуй что-нить типа:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
SELECT min(A.value), max(A.value), A.recid
FROM table A
LEFT JOIN 
(SELECT tdate, min(recid) min_id, max(recid) max_id
FROM table
GROUP BY tdate) B
ON A.tdate = B.tdate
WHERE NOT(((A.recid = B.min_id) OR (A.recid = B.max_id)) AND (A.tdate = B.tdate))
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33957655
alex_sm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну и, конечно, индексы создай, если нет
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33958782
puzzle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за сообщения. Извините, что сразу не описал подробно.
Существует две таблицы

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE "public"."data" (
  "RECID" INTEGER NOT NULL, 
  "NAME" VARCHAR( 30 ) NOT NULL, 
  "TTS" TIMESTAMP WITH TIME ZONE NOT NULL, 
  "VOLLOT" INTEGER NOT NULL, 
  "LAST" NUMERIC( 16 , 2 ) NOT NULL, 
  CONSTRAINT "data_P" PRIMARY KEY("RECID")
) WITHOUT OIDS;

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
CREATE TABLE "public"."data_day" (
  "RECID" INTEGER NOT NULL, 
  "NAME" VARCHAR( 30 ) NOT NULL, 
  "TTS" TIMESTAMP WITH TIME ZONE NOT NULL, 
  "VOLLOT" INTEGER NOT NULL, 
  "OPEN" NUMERIC( 16 , 2 ), 
  "HIGH" NUMERIC( 16 , 2 ), 
  "LOW" NUMERIC( 16 , 2 ), 
  "CLOSE" NUMERIC( 16 , 2 ), 
  CONSTRAINT "data_day_P" PRIMARY KEY("RECID")
) WITHOUT OIDS;

Data, как уже говорил 50.000.000 записей.

Необходимо:
один раз обработать таблицу, и сформировать таблицу дневных данных. Где будут данные за каждый день по каждому "NAME" и со значениями "LAST" Максимальной, Минимальной, Первой (не включая первую запись), Последней (не включая последнюю запись относительно "TTS", "RECID"), и сумма LAST за весь день. Всё это записать в "data_day".

Как я понимаю это надо оформить в виде функции (плохо знаю, синтатксис страдает.).
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
CREATE FUNCTION Create_day RETURNS oid AS 
DECLAIR 
 ID_FIRST INTEGER,
 ID_LAST INTEGER,
 VAL_MIN DOUBLE,
 VAL_MAX DOUBLE
 VAL_OPEN DOUBLE,
 VAL_CLOSE DOUBLE,
 VOL INTEGER,
 DATE  DATE,
 NAME TEXT
BEGIN
while ( $DATE = "select "TTS" from t where date("TTS")>$DATE order by tdate limit 1" )
 while ( $NAME = "select "NAME" from t where date("TTS")=$DATE and "NAME">$NAME order by tdate limit 1" )

$ID_FIRST = "select recid from t where date("TTS")=$DATE and "NAME"=$NAME order by recid limit 1" 
$ID_LAST = "select recid from t where date("TTS")=$DATE and "NAME"=$NAME  order by recid desc limit 1"

$VAL_MIN = "select value from t where date("TTS")=$DATE and "NAME"=$NAME  and recid not in ( $ID_FIRST, $ID_LAST ) order by value limit 1" 
$VAL_MAX = "select value from t where date("TTS")=$DATE and "NAME"=$NAME  and recid not in ( $ID_FIRST, $ID_LAST ) order by value desc limit 1"

$VAL_OPEN = "select value from t where date("TTS")=$DATE and "NAME"=$NAME  and recid not in ( $ID_FIRST, $ID_LAST ) order by tdate desc limit 1"
$VAL_CLOSE = "select value from t where date("TTS")=$DATE and "NAME"=$NAME  and recid not in ( $ID_FIRST, $ID_LAST ) order by tdate limit 1"

$VOL= "select sum(value) from t where date("TTS")=$DATE and "NAME"=$NAME  and recid not in ( $ID_FIRST, $ID_LAST )"

INSERT INTO data_day("TTS","OPEN","HIGH","LOW","CLOSE","VOLLOT") VALUES ($DATE,$VAL_OPEN,$VAL_MAX,$VAL_MIN,$VAL_CLOSE,$VOL)
END
' LANGUAGE 'plpgsql';

Что-то типа того? Вот только с синтаксисом надо разобраться.(( И с индексами..
...
Рейтинг: 0 / 0
Помогите с запросом.
    #33959698
LeXa NalBat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
puzzleНеобходимо:
один раз обработать таблицу, и сформировать таблицу дневных данных. Где будут данные за каждый день по каждому "NAME" и со значениями "LAST" Максимальной, Минимальной, Первой (не включая первую запись), Последней (не включая последнюю запись относительно "TTS", "RECID"), и сумма LAST за весь день. Всё это записать в "data_day"."сумма LAST за весь день" - в этом случае стоит использовать group by, так как придется "прочесывать" всю таблицу.

"не включая последнюю запись относительно TTS, RECID" - не понятно при каком упорядочивании, уточните пожалуйста. по времени?

в полученной таблице data_day поле tts по сути является датой, а не timestamp?

в полученной таблице data_day комбинация полей (name,tts) уникальна?

что такое recid в таблице data_day, как его получать/вычислять?

за основу наверное надо будет взять такой запрос:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
select
  date_trunc('day',tts) as dt,
  name as nm,
  max(last) as mx,
  min(last) as mn
from
  data
group by
  dt, nm
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Помогите с запросом.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]