green_fr: (Default)
[personal profile] green_fr

У меня есть таблица с курсами ценных бумаг. Скажем, колонки POS_DARR, POS_COD и POS_COURS для даты, кода бумаги и курса.
В программе, заполняющей эту таблицу могут быть баги, когда курс застывает на некотором значении, и перестаёт обновляться, т.е. начиная со дня баги курс будет равен одному и тому же значению.
Мне нужно вывести все подозрительные линии, т.е. для некоторой даты вывести все коды, курсы которых не изменились по крайней мере со вчерашнего дня (халява), а затем дату, с которой этот курс оставался неизменным.

Я написал следующего монстра (POSITION - таблица курсов, код не в одной колонке POS_COD, а в двух POS_PTF_COD и POS_VAL_COD, INTEGRATION - список всех дат базы данных):

select pos_darr, min(int_darr), pos_ptf_cod, pos_val_cod, pos_cours
from (
select pos1.pos_darr, int_darr, pos1.pos_ptf_cod, pos1.pos_val_cod, pos1.pos_cours
from position pos1, position pos2, integration
where pos1.pos_darr = '20/07/2006'
and pos1.pos_val_cod = 'FR0000108664'
and pos1.pos_ptf_cod = '1000101'
and pos1.pos_ptf_cod = pos2.pos_ptf_cod
and pos1.pos_val_cod = pos2.pos_val_cod
and int_darr < pos1.pos_darr
and pos1.pos_darr > pos2.pos_darr
and int_darr <= pos2.pos_darr
group by pos1.pos_darr, pos1.pos_ptf_cod, pos1.pos_val_cod, pos1.pos_cours, int_darr
having min(pos2.pos_cours) = max(pos2.pos_cours)
)
group by pos_darr, pos_ptf_cod, pos_val_cod, pos_cours

Монстра работает, конечно, но только когда я запрашиваю один код (как это сдалено в примере). Когда прошу много - думает тормозит. Неудивительно, впрочем. Есть какие-то идеи, как вообще такие вещи пишутся?

Можно, конечно, писать не запрос, а цикл, который пробегает по курсору... Но хочется красиво как-то.

Date: 2006-08-08 04:24 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Для простоты предположим, что курс есть на каждый день для каждой бумаги. И только один в день, т.е. все DARR - это date, а не datetime.

Date: 2006-08-08 04:35 pm (UTC)
From: [identity profile] aguti.livejournal.com
Очень сложная задача и интересная, невозможна без рекурсии и, как следствие, курсора (ИМХО). Я еще подумаю на досуге, сейчас убегаю.
Но твое решение (твой монстр) неверно, т.к. не учитывает факта, что интересует последовательная смена (то есть не просто минимальное, а минимальное из непосредственной близости к текущему).
Выполни своего монстра на 1,3 и поймешь, о чем я.

Date: 2006-08-08 05:14 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Постой, я для того и сделал монстра, чтобы учесть этот случай (иначе совсем просто - минимум даты, на которой курс равен нынешнему). И вроде как проверил...

Без рекурсии тоже делается, но циклом: список бумаг, у которых курс сегодня равен вчерашнему, а потом по этому списку запрос типа минимум даты, на которой count(курсы между изначальной датой и этой) без фильтра равен count(того же самого) с фильтром "курс тот же, что вчера". Но я хочу ещё и без единого гвоздя цикла :-)

Date: 2006-08-08 06:59 pm (UTC)
From: [identity profile] aguti.livejournal.com
А ты свой примерчик проверь. У меня сейчас нет под рукой базы, поэтому не могу тебе точно сказать, но выдает фигню. Но может это я ошиблась, завтра еще раз проверю.
Список - правильное решение, но сложное, потому что много count, будет тормозить.
Самое правильное, на мой взгляд, решение - это завести триггер на апдейт и каждый раз сохранять эту дату в какой-нибудь статистической табличке, откуда потом выдирать одним э-ле-мен-тар-ным селектом. Но мы ведь не ищем простых путей, как я поняла? :)

Date: 2006-08-08 07:53 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Ты будешь смеяться, но база вообще read-only, единственный update происходит по утрам, нашим скриптом, который закачивает новый день. Т.е. даже триггер не понадобится. Но ты правильно заметила про лёгкие пути. Лажа :-)

Date: 2006-08-09 07:27 am (UTC)
From: [identity profile] aguti.livejournal.com
Для меня эта задачка представляет скорее теоретический интерес для исследований возможностей SQL. В производство я даже твоего монстра не поставила бы - только триггер (ну или процедуру), и простые селекты, которые легко читаются. Иначе замучаешься дебаггить и оптимизировать индексы, а любое легкое изменение условий приведет к еще одной неделе творческой работы с SQL - три дня понять, что было написано и еще 4 чтобы правильно это исправить :).

Date: 2006-08-09 06:34 am (UTC)
From: [identity profile] green-fr.livejournal.com
Ачипятался, всесто "and pos1.pos_darr > pos2.pos_darr" читать "and pos1.pos_darr >= pos2.pos_darr", тогда всё работает :-)

Ладно, время не ждёт, начинаю писать процедуру (если что, так и скажу "les gens d'Oracle m'ont dit..."). Но если появятся какие идеи - говори, ага?

P.S. Я только что понял, в какую сторону смотри зверёк на твоём userpic :-))) Раньше мне там виделась часть морды, направленной влево вниз, т.е. вообще все пиксели - это мех, мех, мех %-)

Profile

green_fr: (Default)
green_fr

May 2025

S M T W T F S
    1 23
4 5 678910
11 12 1314 15 1617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 24th, 2025 09:25 pm
Powered by Dreamwidth Studios