Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 31.10.08 20:12
Оценка:
Привет всем!

Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу

В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)

01.11.08 12:04: Перенесено модератором из 'О жизни' — Хитрик Денис
Re: Сложно-алгоритмо-фобия
От: minorlogic Украина  
Дата: 31.10.08 20:26
Оценка:
Здравствуйте, __kain, Вы писали:


__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


Пример в студию , может не все так плохо то ?
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re: Сложно-алгоритмо-фобия
От: russian_bear  
Дата: 31.10.08 21:13
Оценка: 5 (2) +2 :)
__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)

http://www.rsdn.ru/res/book/prog/refactoring.xml
Автор(ы): Мартин Фаулер, Кент Бек, Джон Брант, Дон Робертс, Уильям Апдайк

К тому времени как объектная технология — в частности язык Java — стала обычным
делом, появилось большое количество плохо спроектированных, неэффективных и
малопригодных к сопровождению и расширению приложений. Профессиональные
разработчики программных систем все яснее видят, насколько трудно иметь дело с
таким "неоптимальным" наследием. Уже несколько лет эксперты в области объектного
программирования применяют расширяющийся набор приемов, призванных улучшить
структурную целостность и производительность таких программ. Этот подход,
называемый рефакторингом, до сего момента оставался территорией экспертов,
поскольку не предпринималось попыток перевести профессиональные знания в форму,
доступную всем разработчикам.В данной книге Мартин Фаулер показывает,
как разработчики программного обеспечения могут реализовать существенные выгоды
этой новой технологии, где обычно лежат возможности изменения структуры и как
приступить к переделке плохого проекта в хороший. Каждый шаг рефакторинга прост
— на первый взгляд слишком прост, чтобы сделать его. Это может быть перемещение
поля из одного класса в другой, вынесение какого-то кода из метода и превращение
его в самостоятельный метод или даже перемещение кода по иерархии классов.
Каждый отдельный шаг может показаться элементарным, но совокупный эффект таких
малых изменений в состоянии радикально улучшить проект. Рефакторинг является
верным способом предотвращения распада программы. Помимо описания различных
приемов автор предоставляет подробный каталог, включающий более семидесяти
рефакторингов, а также полезные указания по их применению, пошаговые инструкции
и практические примеры. Примеры написаны на Java, но идеи применимы к любому
объектно-ориентированному языку программирования.
Re: Сложно-алгоритмо-фобия
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 31.10.08 22:12
Оценка: +1
Помогает писать на функциональном языке с более совершенными инструментами декомпозиции.
Ce n'est que pour vous dire ce que je vous dis.
Re[2]: Как часто и почему мы меняем работу
От: blackhearted Украина  
Дата: 01.11.08 07:58
Оценка: +1
Здравствуйте, Don Reba, Вы писали:

DR>Помогает писать на функциональном языке с более совершенными инструментами декомпозиции.


На PL/SQL
Re[2]: Сложно-алгоритмо-фобия
От: gyraboo  
Дата: 01.11.08 08:03
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

__>>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


M>Пример в студию , может не все так плохо то ?


Действительно, было бы интересно увидеть примеры. Ведь многие классы задач, требующих многоэтажные конструкции if или switch при процедурном подходе,
очень изящно решаются с помощью ООП (Джаву можно подключить через PL/SQL). Кстати, это уже будет не алгоритм в классическом понимании этого слова, а какая-нибудь "бизнес-логика", под которую ООП заточено очень хорошо.
Re: Сложно-алгоритмо-фобия
От: 0K Ниоткуда  
Дата: 01.11.08 08:50
Оценка:
Здравствуйте, __kain, Вы писали:

__>Привет всем!


__>И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу


Ну и что? В жизни встречаются сложные вещи.

__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)


А не нужно с ней бороться, это полезная фобия. Она удержит вас от того, чтобы всю жизнь искать философский камень и не найти.
Re: Сложно-алгоритмо-фобия
От: klopodav  
Дата: 01.11.08 10:28
Оценка: 3 (1)
__>Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу

Конкретно для PL/SQL большое количество строк не так уж страшно, т.к. процедура на много строк может сожержать один-единственный SQL-запрос, код которого может быть даже не на один экран. (причем длинный код запроса получается при аккуратном его форматировании, т.е. когда каждая значащая часть кода вынесена на отдельную строку). И в большинстве случаев правильнее этот запрос так и оставить и поручить его оптимизацию базе, чем пытаться вручную декомпозировать (и, соотвественно, получить вместо одного SQL-запроса несколько).

А бороться с фобией сложных процедур надо традиционными методами — подробным комментированием: что делается, зачем и почему именно так
Re[2]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 01.11.08 19:42
Оценка:
Сорри, интернета не было, скоро отпишусь Код будет, принесу в рабочий день!
Re[3]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 01.11.08 20:29
Оценка:
Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.

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

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

Наверное, не стоит углубляться в дебри заморочек, именуемых бизнесс-правилами, обрисую общую ситуацию. Есть шаблон расписания, с привязкой к дате начала его действия. У расписания есть временные интервалы — периоды, в течение которых человек должен быть "внутри". Расписания бывают разных приоритетов (1-основное, 2-исключений). Накладывая 2 на 1, получаем "реальное" положение дел.

Для того чтобы оценить, когда кто должен ходить, нужно сгенерировать последовательность интервалов с привязками к конкретной дате и времени, а потом в этой последовательности указывать, кто и как ходил. Так вот самое неприятное — генерировать эту последовательность... Потому как нужно правильно отметить студента, учесть правила, ... В этом моменте наслаиваются правила трех подсистем — "Расписание", "Кадры студентов", "Рабочая нагрузка на преподавателей". И поэтому генерировать не просто В общем все это — приамбула к коду ))))))))
Re[4]: Сложно-алгоритмо-фобия
От: klopodav  
Дата: 02.11.08 05:43
Оценка: +1
__>Для того чтобы оценить, когда кто должен ходить, нужно сгенерировать последовательность интервалов с привязками к конкретной дате и времени, а потом в этой последовательности указывать, кто и как ходил. Так вот самое неприятное — генерировать эту последовательность... Потому как нужно правильно отметить студента, учесть правила, ... В этом моменте наслаиваются правила трех подсистем — "Расписание", "Кадры студентов", "Рабочая нагрузка на преподавателей".
Если вот это все написать в виде комментариев внутри PL/SQL-процедуры, то код уже покажется не таким страшным, как раньше. Тут общий принцип такой: чем сложнее код и чем менее он очевиден — тем больше в нем надо комментариев

А своим первым постом я хотел сказать, что именно для PL/SQL длиная функция и сложная функция — это совсем не одно и то же. Потому что код на PL/SQL — это симбиоз двух подходов к программированию: алгоритмического (чистый PL/SQL) и декларативного (SQL)

Пусть, например, есть какая-нибудь такая функция:

FUNCTION some_proc() RETURN INTEGER
IS
   x INTEGER;
BEGIN

   SELECT <что-то> INTO x 
       FROM <много-много таблиц>
       WHERE( <много-много условий> )
       AND EXISTS(
            SELECT <огромадный вложенный запрос на 100 строк кода...>
       ...
       <и т.д.>
            )

   RETURN x;
END some_proc;


Сложный ли здесь алгоритм? Алгоритм здесь тривиальный: сделали запрос, вернули его результат.
Сложный ли запрос внутри этого алгоритма? Да, запрос сложный.
Надо ли в этом примере декомпозировать алгоритм? Нет, декомпозировать здесь абсолютно нечего. Главное — к запросу и его частям написать хорошие комментарии.

Кстати, если рассматривать запрос на SQL, то для него некий аналог декомпозиции — это завернуть часть запроса в отдельное представление (view). Но это не для всякого запроса можно сделать.
Re[4]: offtopic
От: Pavel Dvorkin Россия  
Дата: 03.11.08 02:42
Оценка:
Здравствуйте, __kain, Вы писали:

__>Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.


__>На данный момент, я перерабатываю систему учета посещаемости студентов ВУЗа (пишу заново). Данные для оценки посещений получаются автоматически, за счет проходных турникетов. Можно сказать, что такой подход не точен (мало ли где в универе студент шляется), но практика показала, что если в системе посещаемости студент не ходит, то он и в действительности не ходит.


Хм... Вообще-то последнее утверждение тривиально — если, конечно, нельзя пройти помимо турникета.

Если не секрет — какой университет ? Мне просто как преподавателю интересно... Честно говоря, мне бы и в голову не пришло бы, что такое где-нибудь может быть.
With best regards
Pavel Dvorkin
Re[5]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 03.11.08 07:40
Оценка:
Здравствуйте, klopodav, Вы писали:

K>А своим первым постом я хотел сказать, что именно для PL/SQL длиная функция и сложная функция — это совсем не одно и то же. Потому что код на PL/SQL — это симбиоз двух подходов к программированию: алгоритмического (чистый PL/SQL) и декларативного (SQL)


K>Сложный ли здесь алгоритм? Алгоритм здесь тривиальный: сделали запрос, вернули его результат.

K>Сложный ли запрос внутри этого алгоритма? Да, запрос сложный.
K>Надо ли в этом примере декомпозировать алгоритм? Нет, декомпозировать здесь абсолютно нечего. Главное — к запросу и его частям написать хорошие комментарии.

Абсолютно с Вами согласен!

K>Кстати, если рассматривать запрос на SQL, то для него некий аналог декомпозиции — это завернуть часть запроса в отдельное представление (view).


Да, в принципе я так и делаю. Однообразные соединения отправляю во вью, а потом их использую. В общем, подождите пару дней, не буду голословным и приведу пример!

2 Pavel Dvorkin
ВУЗ Ростовский, называется РГУПС (Ростовский Государственный Университет Путей Сообщения).

Задумка получения "халявных" данных о посещаемости хорошая, осталось ее до ума довести А вообще эта система — любимая погремушка деканатов и проректоров
Re: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 03.11.08 14:44
Оценка: 75 (3) +2
Здравствуйте, __kain, Вы писали:

__>Привет всем!


__>Я работаю программистом баз данных, в основном занимаюсь тем, что пишу процедуры на PL/SQL. Специальность у меня — Информационные технологии, так что к созданию программ на основе процедурного подхода подхожу довольно грамотно — разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк. Когда так получается, я считаю, что программа написана правильно. Но иногда встречаются задачи, которые очень трудно разбить, или при разбиении получается слижком громоздкие конструкции. И программа получается довольно сложной. Смотрю я на нее, и впадаю в уныние — потому что упростить не могу


__>В общем вопрос — как бояться со сложно-алгоритмо-фобией? =)



Сложно посоветовать что-то конкретное, поэтому ограничусь
общими советами.

1. Сначала надо разобраться с логической структурой базы данных,
упростить в случае необходимости. Сложность алгоритмов зависит
от того, насколько хорошо спроектирована база данных. В твоем случае
структура базы довольно сложная, тем более что используются темпоральные
данные, так что этому надо уделить особое внимание.

2. Процедурный код упрощается путем разбиения на части, как ты и делаешь.
Код со сложной логикой (признак такого кода — много сложных вложенных операторов
if, в которых трудно разобраться) можно упростить, например, если сначала
описать решение при помощи таблицы решений, а потом уже на ее основе
писать код.

3. Сложные SQL-запросы можно упростить несколькими способами:
— Использовать представления для выделения отдельных частей
запроса, как уже было сказано выше.
— Использовать WITH для улучшения читабельности запроса
(описано, например, в блоге Кевина Мида).
— Писать свои функции для упрощения сложных выражений в запросах
— Использовать табличные функции.
Re: Сложно-алгоритмо-фобия
От: Кодёнок  
Дата: 04.11.08 17:39
Оценка:
Здравствуйте, __kain, Вы писали:

__>разбиваю сложные алгоритма на части, те еще бью, и так до процедур размером в 20-50 строк.


правильно делаешь

__>Смотрю я на нее, и впадаю в уныние


неправильно делаешь
Re[2]: Сложно-алгоритмо-фобия
От: Aikin Беларусь kavaleu.ru
Дата: 05.11.08 07:55
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD> — Использовать WITH для улучшения читабельности запроса

Спасибо за With Отличное средство декомпозиции.
Re[3]: Сложно-алгоритмо-фобия
От: Plague Россия 177230800
Дата: 05.11.08 14:25
Оценка: 1 (1)
A>Спасибо за With Отличное средство декомпозиции.

Уже обсуждалось и тут тоже... CTE (Common Table Expressions) называется... Очень удобно использовать для рекурсий, построения деревьев, например, в MS SQL... в оракле для этого давно CONNECT BY есть, при этом в Оракле CTE и CONNECT BY можно смешивать ...

Вот в MS SQL есть табличные функции с параметрами, а в Оракле ничего подобного нет, но в Оракле есть Пакеты, а подобного нет в MS SQL... они словно сговорились... =((
Re[4]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 05.11.08 19:53
Оценка:
2 Flying Dutchman
> В твоем случае структура базы довольно сложная, тем более что используются темпоральные данные, так что этому надо уделить особое внимание.
Структуру я весь диплом проектировал, и потом еще месяц =) Она получилась универсальной и вроде более-менее простой, но, действительно, наличие темпоральных данных только усложняет дело. Причем все эти данные могут потом еще и перегенерироваться (полностью и частично)... Я тут подумал, нужно наверное в структуру еще что-то добавить, чтобы в коде нужно было проводить меньше вычислений.

> Код со сложной логикой (признак такого кода — много сложных вложенных операторов if, в которых трудно разобраться)

В моем случае, это большая вложенность и большая осмысленность каждого курсора выборки данных...

> 3. Сложные SQL-запросы можно упростить несколькими способами:

Спасибо

В общем я понял, нет неразрешаемых проблем, просто мне нехватает теоретической базы Буду изучать предложенную матчасть

Наконец принес код. Прошу не вчитываться в него, это только пробный вариант, да и непонятен он будет. Просто взгляните на картинку
DECLARE
  PROCEDURE BuildIntervalSeq(p_att_User  IN 
                             p_date_from IN TIMESTAMP := NULL,
                             p_date_to   IN TIMESTAMP := NULL) IS
                             
    v_priority_idz    isa_att.TimeTableType.idz%TYPE;
    v_time_table_idz  isa_att.TimeTable.idz%TYPE;
    v_index           BINARY_INTEGER;
    v_date_offset     TIMESTAMP;
    v_interval_offset TIMESTAMP;
    v_time_step       INTERVAL DAY TO SECOND := p_att_common.GetSingleAdjustment('STUD_RASP_DUR');
    
    TYPE IntervalArray IS TABLE OF isa_att.TimeInterval%ROWTYPE;
    v_intervalArray  IntervalArray;
    
    -- Выбрать типы расписаний по приоритетам.
    CURSOR cTimeTablePriority IS
      SELECT idz
        FROM isa_att.TimeTableType
       ORDER BY priority ASC;
    
    -- Выбираем расписания, принадлежащие
    -- иерархическим группам студентов.
    CURSOR cTimeTableCur IS
      SELECT TimeTable_view.*
        FROM isa_att.TimeTable_view,
             isa_att.HierarchyGroup
       WHERE HierarchyGroup.s_HierarchyType = p_att_common.GetSingleAdjustment('STUD_HIERARCHY')
         AND TimeTable_view.s_Timetabletype = v_priority_idz
         AND TimeTable_view.s_HierarchyGroup = HierarchyGroup.Idz
         AND SYSTIMESTAMP BETWEEN TimeTable_view.Validfrom
                              AND NVL(TimeTable_view.ValidTo, SYSTIMESTAMP);
    
    CURSOR cTimeIntervals IS
      SELECT *
        FROM isa_att.TimeInterval
       WHERE s_TimeTable = v_time_table_idz
       ORDER BY fl_nad_chertoy DESC, TimeOffset;
       
    -- Выбираем расписание и валидных
    -- юзеров для этого времени
    CURSOR cTimeTableValidView IS
      SELECT *
        FROM isa_att.TimetableValid_View
       WHERE s_TimeTable = v_time_table_idz
         AND s_attUser = (SELECT idz FROM isa_att.AttUser where s_teksost = 40351);
  BEGIN
    v_intervalArray := IntervalArray();
    
    FOR curPriority IN cTimeTablePriority LOOP
      v_priority_idz := curPriority.Idz;
      FOR curTimeTable IN cTimeTableCur LOOP
        v_time_table_idz := curTimeTable.Idz;

        -- Выбираем в массив для многократного использования
        OPEN cTimeIntervals;
        FETCH cTimeIntervals BULK COLLECT INTO v_intervalArray;
        CLOSE cTimeIntervals;
        
        FOR curUserValidView IN cTimeTableValidView LOOP
          -- Получили временную метку начала расписания: отступаем "назад" до понедельника,
          -- т.к. занятия начинаются не обязательно в понедельник, а отсчет
          -- временных интервалов начинается с понедельника.
          v_date_offset := curTimeTable.ValidFrom - TO_NUMBER(TO_CHAR(curTimeTable.Validfrom, 'D')) + 1;
          
          -- <Перебираем даты>
          LOOP
            EXIT WHEN v_date_offset > curTimeTable.ValidTo;
            
            -- <Перебираем интервалы>
            v_index := v_intervalArray.FIRST;
            LOOP
              EXIT WHEN v_index IS NULL;
             
              v_interval_offset := v_intervalArray(v_index).TimeOffset + v_date_offset;
              IF  v_intervalArray(v_index).fl_nad_chertoy = 0 THEN
                v_interval_offset := v_interval_offset + 7;
              END IF;
               
              IF v_interval_offset  >= curTimeTable.ValidFrom THEN
                --dbms_output.put_line(TO_CHAR(v_interval_offset, 'DD.MM.YYYY HH24:MI'));
                DoLogic (v_interval_offset,
                     v_intervalArray(v_index).Duration,
                     curUserValidView.s_AttUser,
                     curUserValidView.Validfrom,
                     curUserValidView.Validto,
                     curTimeTable.s_Hierarchygroup,
                     curTimeTable.Idz,
                     v_intervalArray(v_index).idz);
              END IF;
                         
              v_index := v_intervalArray.NEXT(v_index);
            END LOOP; -- </Перебираем интервалы>
            
            v_date_offset := v_date_offset + v_time_step;
          END LOOP; -- </Перебираем даты>
        END LOOP; -- </Перебираем пользователей>
      END LOOP;
    END LOOP;
  END;
  
BEGIN
  BuildIntervalSeq;
END;
Re[5]: offtopic
От: maggot  
Дата: 06.11.08 00:55
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, __kain, Вы писали:


__>>Сейчас попытаюсь в двух словах описать проблему, которую я решаю, а позже приведу код.


__>>На данный момент, я перерабатываю систему учета посещаемости студентов ВУЗа (пишу заново). Данные для оценки посещений получаются автоматически, за счет проходных турникетов. Можно сказать, что такой подход не точен (мало ли где в универе студент шляется), но практика показала, что если в системе посещаемости студент не ходит, то он и в действительности не ходит.


PD>Хм... Вообще-то последнее утверждение тривиально — если, конечно, нельзя пройти помимо турникета.


PD>Если не секрет — какой университет ? Мне просто как преподавателю интересно... Честно говоря, мне бы и в голову не пришло бы, что такое где-нибудь может быть.

Такое даже в некоторых школах (в Москве) есть.
У учеников есть персональные магнитные карты, которые они прикладывают к турникету. В этот момент на экране монитора у охранника высвечивается фотография ученика и какие-то данные (наверное опаздывает ли учник в соответствии с расписанием). Если опаздывает, могут поругать =))
А также записывается в базу данных время входа и выхода из школы. В конце каждого месяца данные распечатываются и передаются классному руководителю.
Re[6]: offtopic
От: __kain Россия  
Дата: 06.11.08 07:25
Оценка:
Здравствуйте, maggot, Вы писали:

M>Такое даже в некоторых школах (в Москве) есть.

M>У учеников есть персональные магнитные карты, которые они прикладывают к турникету. В этот момент на экране монитора у охранника высвечивается фотография ученика и какие-то данные (наверное опаздывает ли учник в соответствии с расписанием). Если опаздывает, могут поругать =))
M>А также записывается в базу данных время входа и выхода из школы. В конце каждого месяца данные распечатываются и передаются классному руководителю.

У мну подсистема связана с кадрами, рабочей нагрузкой и учебным расписанием. Отчет выдается в виде соответствия расписания и посещения его человеком, т.е. автоматизация полная. Если сделать тупо, то да, за месяц можно. А если сделать нормально — с учетом плавающих, периодических и других графиков посещений, то тут прийдется извилины напрягать!
Re[5]: Сложно-алгоритмо-фобия
От: fmiracle  
Дата: 06.11.08 07:58
Оценка: +1
Здравствуйте, __kain, Вы писали:

__>Наконец принес код. Прошу не вчитываться в него, это только пробный вариант, да и непонятен он будет. Просто взгляните на картинку


Итого, что я вижу — несколько запросов, все под курсоры и далее пошла их ручная обработка в циклах...

Можно я выступлю с радикальным предложением?

А тебе точно надо все это писать на Pl/SQL? Может вынести обработку данных из базы в отдельное приложение, написанное на Java или .NET?
Меня вообще немного коробит, когда в SQL-коде появляются курсоры и циклы, а тут в относительно небольшой процедуре 4 вложенных цикла да еще и условное ветвление в теле, а все запросы — только для курсоров...

Нафига, а?
Императивная обработка данных гораздо лучше делается в императивных языках. А ООП для данной задачи позволит лучше ее декомпозировать, построить более красивое и удобное решение. Из базы тянуть естественно не все, а только то что надо, отдельными запросами (либо более "чистыми" хранимками, либо вообще через view)

SQL хорош для описания декларативных запросов, которые потом база эффективно оптимизирует и выбирает нужные данных. Оптимизировать циклы и прочую императивщину база умеет очень плохо. Фактически, вынеся императивную обработку из процедуры на верхний уровень можно получить даже заметное увеличение производительности (зависит от объемов данных и сложности вычислений над ними).
И уж точно будет удобнее программировать (именно в императивном стиле), чем может предложить PL/SQL...
Re[6]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 06.11.08 15:35
Оценка:
Здравствуйте, fmiracle!

За Java или .NET меня по голове не полгадят, но сделать по-другому мало мальский читаемый и понимаемый с первого взгляда код, видимо по-другому не выйдет.

Кстати, а что вы думаете на счет объектных возможностей Oracle? Может с помощью них получится нормально сделать?
Re[7]: Сложно-алгоритмо-фобия
От: fmiracle  
Дата: 06.11.08 17:40
Оценка:
Здравствуйте, __kain, Вы писали:

__>Здравствуйте, fmiracle!

__>За Java или .NET меня по голове не полгадят, но сделать по-другому мало мальский читаемый и понимаемый с первого взгляда код, видимо по-другому не выйдет.

Это аспирантская работа? Расскажи, что это новое и перспективное направление

Серьезно же — я просто не вижу резона, почему это должно строиться чисто на PL SQL. Интерфейс приложения на чем делается? Или тоже возможностми самого Оракла?

__>Кстати, а что вы думаете на счет объектных возможностей Oracle? Может с помощью них получится нормально сделать?


К сожалению, ничего не могу сказать, не работал.
Но можно, например, писать в Оракле хранимки на Java. Непосредственно это я тоже не пробовал, но пробовал аналогичные хранимки на .net в MS SQL — для сложной императивной обработки вполне приятно.
Re[5]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 06.11.08 19:21
Оценка:
Здравствуйте, __kain, Вы писали:


__>Наконец принес код. Прошу не вчитываться в него, это только пробный вариант, да и непонятен он будет. Просто взгляните на картинку


Код написана с использованием курсоров, что сильно усложняет
программу (в принципе, в 95% всех задач курсоры не нужны).
Если переписать все в декларативном виде без курсоров,
программа получится значительно проще.
Re[8]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 07.11.08 11:22
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Это аспирантская работа? Расскажи, что это новое и перспективное направление

Нет, это подсистема промышленного сервера

F>Серьезно же — я просто не вижу резона, почему это должно строиться чисто на PL SQL. Интерфейс приложения на чем делается? Или тоже возможностми самого Оракла?

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

2 Flying Dutchman
F>Код написана с использованием курсоров, что сильно усложняет
F>программу (в принципе, в 95% всех задач курсоры не нужны).
F>Если переписать все в декларативном виде без курсоров,
F>программа получится значительно проще.
Не понял, что вы имеете в виду? По-моему так наоборо проще, селектов в коде нету
Re[9]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 10.11.08 14:18
Оценка: +1
Здравствуйте, __kain, Вы писали:

__>2 Flying Dutchman

F>>Код написана с использованием курсоров, что сильно усложняет
F>>программу (в принципе, в 95% всех задач курсоры не нужны).
F>>Если переписать все в декларативном виде без курсоров,
F>>программа получится значительно проще.
__>Не понял, что вы имеете в виду? По-моему так наоборо проще, селектов в коде нету

Ну так с селектами оно проще будет, чем с курсорами. Проблема в том, что (судя по
твоему коду) ты думаешь и пишешь в процедурном стиле, тогда как для
эффективной работы на SQL нужно думать по-другому.

Как хорошо кто-то сказал (кажется, Джо Селко):

Before SQL programmers could begin working with OLTP (On-Line Transaction
Processing) systems, they had to unlearn procedural, record-oriented
programming before moving on to SQLs declarative, set-oriented programming


И этот переход к декларативному программированию сложен для
тех, кто занимался только процедурным программированием.

Для сравнения, мой текущий проект во многом похож на твой.
Я участвую в разработке большой системы для компании — поставщика
временного персонала. Программа предназначена для планирования работников,
расстановки их по сменам и т.д. Также используется несколько типов
расписаний с разнами приоритетами (точнее, это данные о доступности работника
для работы в зависимости от дня недели, например). Для получения
данных о доступности в определенный день нужно накладывать разные
типы расписаний друг на друга, а также генерировать интервалы, как у тебя.

Так вот, если я хочу с учетом всех расписаний и т.д. получить информацию
о доступности работников во времени, у меня это все делается одним запросом,
который состоит из 6 довольно простых select'ов, соединенных при помощи union.

Твой код можно сильно упростить, если переписать его чисто декларативно.
(если и не весь, то большую часть).

Если интересуют подробности, сообщи следующую информацию:
— Структуру используемых таблиц
— Точное описание того, что нужно сделать.
Re[9]: Сложно-алгоритмо-фобия
От: fmiracle  
Дата: 10.11.08 15:45
Оценка:
Здравствуйте, __kain, Вы писали:

F>>Серьезно же — я просто не вижу резона, почему это должно строиться чисто на PL SQL. Интерфейс приложения на чем делается? Или тоже возможностми самого Оракла?

__>Если все лежит на сервере, то во-первых, клиенту ставить ничего не нужно (учитывая слабость клиентских машин-это существенный довод). И потом, если будет где-то ошибка, в базе данных ее легче поправить будет.

Понятно, но вообще это ничего не значит Та же проблема решается трехзвенкой — application server к которому уже коннектятся пользователи. Простейший пример — веб-приложения (appServer — iis+asp.net, клиент — браузер).
И к клиентам требования минимальны и изменения производятся только на одной машине.

F>>Если переписать все в декларативном виде без курсоров,

F>>программа получится значительно проще.
__>Не понял, что вы имеете в виду? По-моему так наоборо проще, селектов в коде нету

SQL — декларативный язык, и базы данных ориентированы именно на него. В том числе и по производительности.
Императивные конструкции в хранимках (расширения PlSql) — это костыли, как с точки зрения дизайна, так и эффективности.

Если хочешь программировать чисто в Оракле — изучай глубже SQL и максимально описывай все в запросах, а не пытайся сэмулировать С в Оракле. То есть хранимка остается, но в ней должны быть не итерации по курсорам, а набор запросов (или вообще 1 запрос). Императивные конструкции — в минимальнейшем количестве и наиболее простые (например, условным оператором проверив параметры, или результат запроса, выполнить далее тот или иной запрос). А лучше — вообще без них.

Сперва непривычно, но оно того стоит.
Re[10]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 11.11.08 11:16
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD>

FD>Before SQL programmers could begin working with OLTP (On-Line Transaction
FD>Processing) systems, they had to unlearn procedural, record-oriented
FD>programming before moving on to SQLs declarative, set-oriented programming

Ценная мысль, однако

FD>Твой код можно сильно упростить, если переписать его чисто декларативно.

FD>(если и не весь, то большую часть).

FD>Если интересуют подробности, сообщи следующую информацию:

FD>- Структуру используемых таблиц
FD>- Точное описание того, что нужно сделать.

Для начала приведу упрощенную схему (~6 кб):



Опишу словами. Пользователи объедены в группы, группы выстроены в иерархию. Изменения в верхней точке иерархии спускаются вниз. Если временные интервалы расписания пересекаются, то верхний интервал разбивает нижний. Поясню: пусть нижний интервал начинается в 9:00 и заканчивается в 12:00, то после наложения "верхнего" интервала 10:00-11:00 должно получиться так: 9:00-10:00; 10:00-11:00; 11:00-12:00.

Расписание я организовал так: есть временной шаблон, который повторяется с периодичностью в "Длительность шаблона". Шаблон начинаем применять с "Действительно от". У временного интервала указано смещение во времени относительно начала действия шаблона, указана длительность. В итоге получился гибкий шаблон, под который можно засунуть луюбой график, имеющий период

Итак задача такая: сгенерировать последовательность интервалов с привязкой к конкретной дате, а также учесть иерархию, и приоритет расписания. Если вы очитали до сюда, у Вас крепкие нервы

На мой взгляд, накладывать расписание вниз по иерархии чисто декларативно невозможно.
Re[10]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 11.11.08 11:24
Оценка:
Здравствуйте, fmiracle, Вы писали:

F>Понятно, но вообще это ничего не значит Та же проблема решается трехзвенкой — application server к которому уже коннектятся пользователи. Простейший пример — веб-приложения (appServer — iis+asp.net, клиент — браузер).

F>И к клиентам требования минимальны и изменения производятся только на одной машине.
У нас для трехзвенки Java используется. Но я согласен с Flying Dutchman, в том, что можно сделать проще и на SQL

F>SQL — декларативный язык, и базы данных ориентированы именно на него. В том числе и по производительности.

F>Императивные конструкции в хранимках (расширения PlSql) — это костыли, как с точки зрения дизайна, так и эффективности.

F>Если хочешь программировать чисто в Оракле — изучай глубже SQL и максимально описывай все в запросах, а не пытайся сэмулировать С в Оракле. То есть хранимка остается, но в ней должны быть не итерации по курсорам, а набор запросов (или вообще 1 запрос). Императивные конструкции — в минимальнейшем количестве и наиболее простые (например, условным оператором проверив параметры, или результат запроса, выполнить далее тот или иной запрос). А лучше — вообще без них.


F>Сперва непривычно, но оно того стоит.

Интересный и правильный ход мыслей. Я запомню
Re[11]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 11.11.08 12:57
Оценка:
И вообще я тут подумал — а зачем разбивать интервалы?.. Не брать пересекающиеся, и все. "К чему такая точность" (с) =))
Re[11]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 11.11.08 14:03
Оценка:
Здравствуйте, __kain, Вы писали:



__>Опишу словами. Пользователи объедены в группы, группы выстроены в иерархию. Изменения в верхней точке иерархии спускаются вниз. Если временные интервалы расписания пересекаются, то верхний интервал разбивает нижний. Поясню: пусть нижний интервал начинается в 9:00 и заканчивается в 12:00, то после наложения "верхнего" интервала 10:00-11:00 должно получиться так: 9:00-10:00; 10:00-11:00; 11:00-12:00.


Я правильно понял, что:
1. "Верхний" интервал — это интервал с большим приоритетом или
2. Стоящий выше в иерархии ?

__>Расписание я организовал так: есть временной шаблон, который повторяется с периодичностью в "Длительность шаблона".


В каких единицах выражается "Длительность шаблона" ?

__>Шаблон начинаем применять с "Действительно от". У временного интервала указано смещение во времени относительно начала действия шаблона, указана длительность.


"Шаблон" — это набор интервалов ?

__>В итоге получился гибкий шаблон, под который можно засунуть луюбой график, имеющий период


Я не совсем в этом разобрался. Не мог бы ты прислать немного данных из таблиц
для примера ? Желательно скрипт в виде набора команд CREATE TABLE для создания
таблиц + INSERT для их заполнения.

__>На мой взгляд, накладывать расписание вниз по иерархии чисто декларативно невозможно.


Посмотрим
Re[12]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 12.11.08 10:39
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD>Я правильно понял, что:

FD>1. "Верхний" интервал — это интервал с большим приоритетом или
FD>2. Стоящий выше в иерархии ?
Оба раза вы правы Пусть есть иерархическая группа: Университет -> Факультет -> Кафедра -> Группа. Тогда, если у Университета есть расписание, то интервалы университета будут более приоритетным ко всем другим интервалам подчиненных узлов.

FD>В каких единицах выражается "Длительность шаблона" ?

INTERVAL DAY TO SECOND

FD>"Шаблон" — это набор интервалов ?

"Шаблон" — набор интервалов и указание их длительности.

FD>Я не совсем в этом разобрался. Не мог бы ты прислать немного данных из таблиц

FD>для примера ? Желательно скрипт в виде набора команд CREATE TABLE для создания
FD>таблиц + INSERT для их заполнения.

Понять действительно сразу не получится — я своему дипломному руководителю вживую полчаса рассказывал, а он программер со стажем...
Ну, держитесь, скрипт для создания схемы и данных:

-- Создание таблицы "Тип расписания"
CREATE TABLE TimeTableType (
  Descript   VARCHAR2(128),
  Priority   NUMBER(1),
  id         NUMBER(1),
  PRIMARY KEY (id)
)

-- Создать таблицу иерархических групп
CREATE TABLE HierarchyGroup (
  id         NUMBER,
  Descript   VARCHAR2(128),
  s_parent   NUMBER,
  PRIMARY KEY (id),
  FOREIGN KEY (s_parent) REFERENCES HierarchyGroup (id)
)

-- Создать таблицу расписание
CREATE TABLE TimeTable (
  id NUMBER,
  ValidFrom TIMESTAMP,
  ValidTo   TIMESTAMP,
  Duration  INTERVAL DAY TO SECOND,
  s_HierarchyGroup NUMBER,
  s_TimeTableType NUMBER(1),
  Descript  VARCHAR2(128),
  PRIMARY KEY(id),
  FOREIGN KEY (s_HierarchyGroup) REFERENCES HierarchyGroup (Id)
)

-- Таблица временных интервалов
CREATE TABLE TimeInterval (
  id NUMBER,
  TimeOffset INTERVAL DAY TO SECOND,
  Duration INTERVAL DAY TO SECOND,
  s_TimeTable NUMBER,
  FOREIGN KEY (s_TimeTable) REFERENCES TimeTable (id),
  PRIMARY KEY (id)
)

-- Вставляем данные
BEGIN
  INSERT INTO TimeTableType (Id, Priority, Descript) VALUES (1, 1, 'Основное расписание');
  INSERT INTO TimeTableType (Id, Priority, Descript) VALUES (2, 2, 'Расписание исключений');

  INSERT INTO HierarchyGroup (Id, Descript, s_Parent) VALUES (1, 'Университет (самый верхний узел)', NULL);
  INSERT INTO HierarchyGroup (Id, Descript, s_Parent) VALUES (2, 'Факультет АТС (родитель-Университет)', 1);
  INSERT INTO HierarchyGroup (Id, Descript, s_Parent) VALUES (3, 'Факультет ДСМ (родитель-Университет)', 1);
  INSERT INTO HierarchyGroup (Id, Descript, s_Parent) VALUES (4, 'Кафедра ВТ и АСУ (родитель-факультет АТС)', 2);
  INSERT INTO HierarchyGroup (Id, Descript, s_Parent) VALUES (5, 'Кафедра АМС (родитель-факультет АТС)', 2);
  INSERT INTO HierarchyGroup (Id, Descript, s_parent) VALUES (6, 'Группа АИ-5-010 (родитель-кафедра ВТ и АСУ)', 4);

  INSERT INTO TimeTable (Id, Validfrom, Validto, Duration, s_Hierarchygroup, Descript, s_TimeTableType)
     VALUES (1,
         TO_TIMESTAMP('01.09.2008', 'DD.MM.YYYY'),
         TO_TIMESTAMP('31.12.2008', 'DD.MM.YYYY'), 
             '+14 00:00:00.0',
         6,
         'Стандартное расписание',
             1);

  FOR l_ned IN 1..5 LOOP
    INSERT INTO TimeInterval (id,         TimeOffset, Duration, s_TimeTable)
                      VALUES ((l_ned-1) * 5 + 1, '+' || TO_CHAR(l_ned-1) || ' 8:20:00.0', '+00 1:30:00.0', 1);

    INSERT INTO TimeInterval (id,         TimeOffset, Duration, s_TimeTable)
                      VALUES ((l_ned-1) * 5 + 2, '+' || TO_CHAR(l_ned-1) || ' 10:05:00.0', '+00 1:30:00.0', 1);

    INSERT INTO TimeInterval (id,         TimeOffset, Duration, s_TimeTable)
                      VALUES ((l_ned-1) * 5 + 3, '+' || TO_CHAR(l_ned-1) || ' 12:05:00.0', '+00 1:30:00.0', 1);

    INSERT INTO TimeInterval (id,         TimeOffset, Duration, s_TimeTable)
                      VALUES ((l_ned-1) * 5 + 4, '+' || TO_CHAR(l_ned-1) || ' 13:50:00.0', '+00 1:30:00.0', 1);
  END LOOP;

  INSERT INTO TimeTable (Id, Validfrom, Validto, Duration, s_Hierarchygroup, Descript, s_TimeTableType)
                 VALUES (2,
             TO_TIMESTAMP('03.09.2008', 'DD.MM.YYYY'),
             TO_TIMESTAMP('03.09.2008', 'DD.MM.YYYY'),
                      '+1 00:00:00.0',
             1,
             '3-го отключили свет, универ закрыли',
             2);

  INSERT INTO TimeInterval (id, TimeOffset, Duration, s_TimeTable)
                  VALUES (25, '+0 0:0:0.0', '+1 0:0:0.0', 2);
  COMMIT;
END;

--Посмотреть дерево иерархии:
SELECT DECODE(level, 1, '', LPAD(' ', level * 5, ' ')) || h.descript AS descript
  FROM HierarchyGroup h
 START WITH s_parent IS NULL
 CONNECT BY s_parent = PRIOR id
Re[13]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 14.11.08 15:47
Оценка:
Здравствуйте, __kain, Вы писали:

Был занят по работе, поэтому сразу не ответил.

__>Оба раза вы правы Пусть есть иерархическая группа: Университет -> Факультет -> Кафедра -> Группа. Тогда, если у Университета есть расписание, то интервалы университета будут более приоритетным ко всем другим интервалам подчиненных узлов.


Каким образом
Допустим, у нас есть расписание Университета:

9:00 — 11:00
14:00 — 16:00

и расписание кафедры

10:00 — 12:00
13:00 — 13:30
15:00 — 17:00

Каким будет результирующее расписание ?

Будут ли интервалы просто складываться или интервал Университета
отменяет интервал кафедры ?

Что касается интервалов для одной и той же иерархической группы,
но с разными приоритетами. Из приведенного ниже примера создается
впечатление, что интервал с приоритетом 2 отменяет все интервалы
с приоритетом 1. То есть для 03.09.2008 в результате не существует
ни одного интервала. Так ли это ?

__>[sql]

__>-- Создание таблицы "Тип расписания"
__>CREATE TABLE TimeTableType (
__> Descript VARCHAR2(128),
__> Priority NUMBER(1),
__> id NUMBER(1),
__> PRIMARY KEY (id)
__>)

__>-- Создать таблицу иерархических групп

__>CREATE TABLE HierarchyGroup (
__> id NUMBER,
__> Descript VARCHAR2(128),
__> s_parent NUMBER,
__> PRIMARY KEY (id),
__> FOREIGN KEY (s_parent) REFERENCES HierarchyGroup (id)
__>)

__>-- Создать таблицу расписание

__>CREATE TABLE TimeTable (
__> id NUMBER,
__> ValidFrom TIMESTAMP,
__> ValidTo TIMESTAMP,
__> Duration INTERVAL DAY TO SECOND,
__> s_HierarchyGroup NUMBER,
__> s_TimeTableType NUMBER(1),
__> Descript VARCHAR2(128),
__> PRIMARY KEY(id),
__> FOREIGN KEY (s_HierarchyGroup) REFERENCES HierarchyGroup (Id)
__>)

Насколько я понимаю,

ValidFrom — дата начала действия расписания
ValidTo — дата окончания действия расписания
Duration — период действия расписания

То есть в приведенном ниже примере создается расписание на 2 недели,
которое циклически повторяется, начиная с ValidFrom.

Вопрос: Это расписание всегда начинается с понедельника или может
начинаться с другого дня недели ?

__>-- Таблица временных интервалов

__>CREATE TABLE TimeInterval (
__> id NUMBER,
__> TimeOffset INTERVAL DAY TO SECOND,
__> Duration INTERVAL DAY TO SECOND,
__> s_TimeTable NUMBER,
__> FOREIGN KEY (s_TimeTable) REFERENCES TimeTable (id),
__> PRIMARY KEY (id)
__>)

Могут ли интервалы из этой таблицы перекрываться ?

Как происходит генерация расписания для определенного узла
иерархии ? В моем представлении так (для приведенного примера):

1. Выбираем узел иерархии
2. Составляем основное расписание на основе расписаний этого
узла и всех родительских узлов
3. Составляем расписание-исключение на основе расписаний этого
узла и всех родительских узлов
4. Начинаем с 01.09.2008, используем интервалы из таблицы
TimeInterval. Для нахождения начала интервала прибавляем
TimeOffset к 01.09.2008 00:00. Для нахождения конца интервала
прибавляем Duration к началу интервала.
При этом применяем расписание-исключение к дате 03.09.2008,
в результате чего на эту дату нет интервалов.
5. Потом переходим к 14.09.2008 и повторяем пункт 3.
6. Повторяем до конца года.
Re[14]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 16.11.08 14:43
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD>Каким образом

FD>Допустим, у нас есть расписание Университета:

FD> 9:00 — 11:00

FD> 14:00 — 16:00

FD>и расписание кафедры


FD> 10:00 — 12:00

FD> 13:00 — 13:30
FD> 15:00 — 17:00

FD>Каким будет результирующее расписание ?


1 интервал: 9:00 — 11:00. Интервал принадлежит университету.
2 интервал: 11:00 — 12:99. Интервал принадлежит кафедре.
3 интервал: 14:00 — 16:00. Интервал принадлежит университету.
4 интервал 16:00 — 17:00. Интервал принадлежит кафедре.

FD>Будут ли интервалы просто складываться или интервал Университета

FD>отменяет интервал кафедры ?

Он не отменяет, он разбивает. Например:

___]---------[ (интервал университета)
|===============| (интервал кафедры).

|==]---------[====| (результрующий интервал).

FD>Что касается интервалов для одной и той же иерархической группы,

FD>но с разными приоритетами. Из приведенного ниже примера создается
FD>впечатление, что интервал с приоритетом 2 отменяет все интервалы
FD>с приоритетом 1. То есть для 03.09.2008 в результате не существует
FD>ни одного интервала. Так ли это ?

Нет. Интервалы в одном расписании никак между собой не пересекаются. Приоритет интервала прямо зависит от его связи с иерархической группой. Чем "выше" группа, тем приоритетней ее интервал.

FD>То есть в приведенном ниже примере создается расписание на 2 недели,

FD>которое циклически повторяется, начиная с ValidFrom.

Все верно

FD>Вопрос: Это расписание всегда начинается с понедельника или может

FD>начинаться с другого дня недели ?

Расписание начинает быть действительным точно во время ValidFrom.

FD>Могут ли интервалы из этой таблицы перекрываться ?


Нет, в пределах расписания интервалы не пересекаются.

FD>Как происходит генерация расписания для определенного узла

FD>иерархии ? В моем представлении так (для приведенного примера):

Алгоритм построения последовательности у меня такой:

1) Начинаем с иерархической группы. Для этой группы строим иерархию "вверх" — то есть, выбираем все вышестоящие группы.
2) Сверху вниз, начинаем генерировать интервалы. Если запись на период действия интервала уже есть, мы ее либо разбиваем, либо удаляем (если наша запись полностью перекрывает уже существующую).

P.S.
Сложновато получается, а? =)
Re[15]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 16.11.08 18:52
Оценка:
Здравствуйте, __kain, Вы писали:

FD>>Что касается интервалов для одной и той же иерархической группы,

FD>>но с разными приоритетами. Из приведенного ниже примера создается
FD>>впечатление, что интервал с приоритетом 2 отменяет все интервалы
FD>>с приоритетом 1. То есть для 03.09.2008 в результате не существует
FD>>ни одного интервала. Так ли это ?

__>Нет. Интервалы в одном расписании никак между собой не пересекаются. Приоритет интервала прямо зависит от его связи с иерархической группой. Чем "выше" группа, тем приоритетней ее интервал.


Непонятно, как происходит наложение расписания исключений на основное расписание.
Еще раз, в приведенном примере расписание исключений содержит интервал для всего дня
на 03.09.2008, то есть по логике вещей все интервалы из основного
расписания, попадающие в это промежуток, отменяются (то есть все
занятия отменяются, потому что в Университете в этот день отключили свет).
Так ли это ?

FD>>Вопрос: Это расписание всегда начинается с понедельника или может

FD>>начинаться с другого дня недели ?

__>Расписание начинает быть действительным точно во время ValidFrom.


Если расписание повторяется циклически
(то есть если Duration < (ValidTo — ValidFrom)),
то значение в колонке Duration таблицы TimeTable должно
быть равно 1 дню или быть кратно 7 дням. Так ли это ?

В противном случае его невозможно будет повторить.
Допустим, например, что Duration = 3. Начиная применять его с понедельника,
получим, что расписания повторяются таким образом:
Пн Вт Ср
Чт Пт Сб
Вс Пн Вт

Что, наверное, является неправильным. Или правильным ?

Не говоря уже о таком Duration, как 2.5 дня и т.д.

__>P.S.

__>Сложновато получается, а? =)

Ну это не самый сложный случай.
Re[16]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 17.11.08 14:17
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD>Здравствуйте, __kain, Вы писали:


FD>>>Что касается интервалов для одной и той же иерархической группы,

FD>>>но с разными приоритетами. Из приведенного ниже примера создается
FD>>>впечатление, что интервал с приоритетом 2 отменяет все интервалы
FD>>>с приоритетом 1. То есть для 03.09.2008 в результате не существует
FD>>>ни одного интервала. Так ли это ?

Интервалы дробятся. Представьте, сидит сторож 12 часов, и на последней минуте его дежурства отключают свет. Мы же не будем отменять весь интервал, только уменьшим для этой даты его продолжительность

FD>Если расписание повторяется циклически

FD>(то есть если Duration < (ValidTo — ValidFrom)),
FD>то значение в колонке Duration таблицы TimeTable должно
FD>быть равно 1 дню или быть кратно 7 дням. Так ли это ?

Расписание начинается с ValidFrom, циклически повторяется с продолжительностью в Duration, и генерация интервалов заканчивается по достижение ValidTo.

Расписание исключений генерирует интервалы точно также. Просто сначала мы проходим снизу вверх с учетом основного расписания, потом мы опять проходим сверху вниз, но с учетом только расписаний исключения.

Я в принципе код набросал, осталось потестить. В декларативном виде без "своих" групповых функций здесь точно не получится...
Re[17]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 17.11.08 14:19
Оценка:
Расписание исключений генерирует интервалы точно также. Просто сначала мы проходим снизу вверх с учетом основного расписания, потом мы опять проходим снизу вверх, но с учетом только расписаний исключения.

Ошибся
Re[17]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 18.11.08 23:01
Оценка: 120 (3)
Я сделал первый вариант решения.

Реализовано для Oracle 10g и выше. Я реализовал только обработку
основных расписаний, но обработка расписаний исключений также может быть
добавлена.

Я произвел следующие изменения в структуре БД (в основном привел к
соответствию к моему собственному стилю — мне так удобнее):

1. Имена таблиц и колонок созданы с использованием '_' в качестве
разделителя слов.

2. Имена колонок — первичных ключей изменены с ID на
<Имя таблицы>_ID. Соответственно изменены имена колонок, используемых
во внешних ключах. Это дает возможность использовать
синтаксис Inner join ... using (...) в запросах.

3. Тип колонок ValidFrom и ValidTo изменен на более логичный тип DATE

4. Тестовые данные — только на английском (мой сервер что-то русские
буквы не воспринимает, а разбираться нет времени).

5. Убрана колонка ID из таблицы TimeInterval.

Все скрипты находятся здесь.

Назначение файлов:

create_db.sql Создание БД
load_test_data.sql Загрузка тестовых данных
create_views.sql Создание представлений

Начинаем с представления V_Hierarchy

-- Get the list of all nodes with all parent nodes
create or replace view V_Hierarchy
as
with hierarchy as (
  select Hierarchy_Group_Id,
         sys_connect_by_path(Hierarchy_Group_Id, '/') || '/' as full_path,
         level as Priority
    from Hierarchy_Group
    start with Parent_Group_Id is null
    connect by Parent_Group_Id = prior Hierarchy_Group_id
 )
 select hier1.Hierarchy_Group_Id as Hierarchy_Group_Id,
        hier2.Hierarchy_Group_id as Participating_Hier_Group_Id,
        hier1.full_path,
        hier2.Priority
   from hierarchy hier1 cross join hierarchy hier2
   where instr(hier1.full_path, '/' || to_char(hier2.Hierarchy_Group_id) || '/') > 0;


Назначение колонок результата:

Hierarchy_Group_Id — идентификатор узла иерархии.
Participating_Hier_Group_Id — идентификатор узла иерархии, начиная от
текущего и до самого верхнего родителя.
Priority — приоритет узла Participating_Hier_Group_Id (1 — самый
высокий).

Следующее представление генерирует все интервалы для всех расписаний,
разворачивая все цикличиские расписания.

create or replace view V_Unrolled_Interval
as
  with numbers as (
     select level num
       from dual
       connect by level <= 100),
  all_interval as (
     select Time_Table_Id,
            Time_Table.Hierarchy_Group_Id,
            Time_Table.Valid_From,
            Time_Table.Valid_To,
            Time_Table.Valid_From +
              Time_Table.Duration * (numbers.num - 1) +
              Time_Interval.Time_Offset as Start_Date_Time,
            Time_Table.Valid_From +
              Time_Table.Duration * (numbers.num - 1) +
              Time_Interval.Time_Offset +
              Time_Interval.Duration as End_Date_Time,
            Time_Interval.duration as Duration
       from Time_Table cross join numbers
         inner join Time_Interval using(Time_table_Id)
     )
   select Hierarchy_Group_Id,
          Time_Table_Id,
          Start_Date_Time,
          End_Date_Time,
          Duration
    from all_interval
    where trunc(Start_Date_Time) <= Valid_To;


Следующее представление добавляет к интервалам каждого узла
иерархии интервалы для родительских узлов.

create or replace view V_All_Unrolled_Interval
as
select V_Hierarchy.Hierarchy_Group_Id,
       V_Hierarchy.Priority,
       V_Unrolled_Interval.Time_Table_Id,
       V_Unrolled_Interval.Start_Date_Time,
       V_Unrolled_Interval.End_Date_Time,
       V_Unrolled_Interval.Duration
  from V_Hierarchy inner join V_Unrolled_Interval
    on V_Hierarchy.Participating_Hier_Group_Id = V_Unrolled_Interval.Hierarchy_Group_Id;


Наконец, самое сложное — комбинирование интервалов с разными
приоритетами.

create or replace view v_combined_interval
as
with
  -- Select all DISTINCT start/end points of all intervals
  all_point as (
    select Hierarchy_Group_Id,
           start_date_time as date_time
      from V_All_Unrolled_Interval
    union
    select Hierarchy_Group_Id,
           end_date_time as date_time
      from V_All_Unrolled_Interval),
  -- Generate sequence of all intervals between consecutive points
  all_interval0 as (
    select Hierarchy_Group_Id,
           date_time as start_date_time,
           lead(date_time) over (partition by Hierarchy_Group_Id order by date_time) as end_date_time
      from all_point
  ),
  -- Remove the last interval with end_date_time is null
  all_interval as (
    select Hierarchy_Group_Id,
           start_date_time,
           end_date_Time
      from all_interval0
      where end_Date_time is not null
  ),
  -- Split all intervals
  split_interval as (
    select V_All_Unrolled_Interval.Hierarchy_Group_Id,
           V_All_Unrolled_Interval.priority,
           all_interval.start_date_time,
           all_interval.end_date_time
      from V_All_Unrolled_Interval cross join all_interval
      where V_All_Unrolled_Interval.Hierarchy_Group_Id = All_Interval.Hierarchy_Group_Id
        and All_Interval.start_date_Time >= V_All_Unrolled_Interval.start_date_Time
        and All_Interval.start_date_Time < V_All_Unrolled_Interval.end_date_Time
  )
  -- Select only intervals with highest priority (= lowest priority value).
  select Hierarchy_Group_Id,
         min(priority) as priority,
         start_date_Time,
         end_date_Time
    from split_interval
    group by Hierarchy_Group_Id, start_date_Time, end_date_time;


Немного пояснений.

Результат представления V_All_Unrolled_Interval
(для одного дня и для Hierarchy_Group_Id = 3)

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1    +--------+     +--+        +-----+  +-----+

2       +--+     +--------+  +-----+        +-----+  +--+

3 +-----+  +--------+     +-----+     +--+


Результат промежуточного запроса ALL_POINT — все начала и концы
всех интервалов:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +


Результат промежуточного запроса ALL_INTERVAL — все интервалы между
всеми последующими точками:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+


Результат промежуточного запроса SPLIT_INTERVAL — все исходные интервалы,
разбитые на меньшие интервалы, определяемые точками из результата
запроса ALL_POINT:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1    +--+--+--+     +--+        +--+--+  +--+--+

2       +--+     +--+--+--+  +--+--+        +--+--+  +--+

3 +--+--+  +--+--+--+     +--+--+     +--+


Результат представления V_COMBINED_INTERVAL — из всех перекрывающихся
интервалов выбраны интервалы с самым большим приоритетом:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1    +--+--+--+     +--+        +--+--+  +--+--+

2                +--+  +--+  +--+              +--+  +--+

3 +--+        +--+        +--+        +--+


Мне кажется, что существует болле простое и элегантное решение,
но я пока не смог его найти.

Как видишь, все сделано декларативно и без курсоров, ни одной строки
процедурного кода.

Описание краткое и несколько сумбурное. Если будут вопросы — пиши.

На этом уже можно было бы остановиться, но приведеное решение
имеет один недостаток — существующие интервалы с приоритетом 1
оказались разбитыми на несколько интервалов.

Я исправлю это через некоторое время.
Re[18]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 19.11.08 09:34
Оценка:
FD>Мне кажется, что существует болле простое и элегантное решение,
FD>но я пока не смог его найти.

FD>Как видишь, все сделано декларативно и без курсоров, ни одной строки

FD>процедурного кода.

FD>Описание краткое и несколько сумбурное. Если будут вопросы — пиши.


FD>На этом уже можно было бы остановиться, но приведеное решение

FD>имеет один недостаток — существующие интервалы с приоритетом 1
FD>оказались разбитыми на несколько интервалов.

FD>Я исправлю это через некоторое время.


Что тут скажешь? Снимаю шляпу, маэстро! Буду разбираться, как у вас это работает Удивительно, как килограммы кода превратились в пару вью... Я немного в прострации сейчас

FD>Мне кажется, что существует болле простое и элегантное решение,

FD>но я пока не смог его найти.

Решение объединить концы и начала.. Браво!
Re[19]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 21.11.08 13:10
Оценка: 3 (1)
Здравствуйте, __kain, Вы писали:

__>Что тут скажешь? Снимаю шляпу, маэстро! Буду разбираться, как у вас это работает


Эти книги помогут тебе разобраться:

Molinaro
SQL Cookbook
ISBN-13: 978-0596009762
Chapter 10. Working with Ranges
Chapter 13. Hierarchical Queries

Walsh & Sikha
Advanced SQL Functions in Oracle 10g
ISBN-13: 978-1-59822-021-6

Ниже улучшенный и дополненный вариант решения.

Реализована только обработка основных расписаний, без
расписаний-исключений.

Сделаны следующие изменения по сравнению с первоначальным решением:

— Новое представление V_Max_Repetition_Number.
— Изменено представление V_Unrolled_Interval.
— Добавлены констрейнты для таблицы Time_Table.
— Добавлены комментарии.
— Изменена структура тестовых данных.
— Добавлены для учебных целей: тестовое представление v_test_interval,
Файл simplified_combined_interval_query.sql, Файл simplified_interval_query.sql
— Добавлено представление V_Interval

Скрипты находятся здесь.

Назначение файлов:

convert_test_data_to_1day.sql
convert_test_data_to_2day.sql
create_db.sql — Создание БД
create_views.sql — Создание представлений
load_test_data_1day.sql — Загрузка тестовых данных
simplified_combined_interval_query.sql — Упрощенный вариант запроса
для представления V_Combined_Interval
simplified_interval_query.sql — Упрощенный вариант запроса
для представления V_Interval
v_test_interval.sql Тестовые данные для запроса из файла
simplified_interval_query.sql

Начинаем с представления V_Hierarchy

-- Get the list of all nodes with all parent nodes
create or replace view V_Hierarchy
as
with hierarchy as (
  select Hierarchy_Group_Id,
         sys_connect_by_path(Hierarchy_Group_Id, '/') || '/' as full_path,
         level as Priority
    from Hierarchy_Group
    start with Parent_Group_Id is null
    connect by Parent_Group_Id = prior Hierarchy_Group_id
 )
 select hier1.Hierarchy_Group_Id as Hierarchy_Group_Id,
        hier2.Hierarchy_Group_id as Participating_Hier_Group_Id,
        hier1.full_path,
        hier2.Priority
   from hierarchy hier1 cross join hierarchy hier2
   where instr(hier1.full_path, '/' || to_char(hier2.Hierarchy_Group_id) || '/') > 0;


Назначение колонок результата:

Hierarchy_Group_Id — идентификатор узла иерархии.
Participating_Hier_Group_Id — идентификатор узла иерархии, начиная от
текущего и до самого верхнего родителя.
Priority — приоритет узла Participating_Hier_Group_Id (1 — самый
высокий).

Следующее представление используется для получения максимального числа
повторений для повторяющихся расписаний:

--------------------------------------------------------------------------
-- Get the maximal repetition number for the cyclic timetables.
-- The value is not exact< but it's guaranteed to be no less that
-- the real value.
--------------------------------------------------------------------------
create or replace view V_Max_Repetition_Number
as
with period_sec as (
select (trunc(Valid_To) - trunc(Valid_From) + 1) * 60 * 60 * 24 as Valid_Period_Sec,
       (to_number(extract(second from Duration)) +
          to_number(extract(minute from Duration)) * 60 +
          to_number(extract(hour from Duration)) * 60 * 60 +
          to_number(extract(day from Duration)) * 60 * 60* 24) as Duration_Sec
  from Time_Table
)
select max(Valid_Period_Sec / Duration_Sec + 1) as Max_Repetition_Number
  from period_Sec;


Следующее представление генерирует все интервалы для всех расписаний,
разворачивая все циклические расписания.

create or replace view V_Unrolled_Interval
as
  with numbers as (
     select level num
       from dual
       connect by level <= (select Max_Repetition_Number from V_Max_Repetition_Number)),
  all_interval as (
     select Time_Table_Id,
            Time_Table.Hierarchy_Group_Id,
            Time_Table.Valid_From,
            Time_Table.Valid_To,
            Time_Table.Valid_From +
              Time_Table.Duration * (numbers.num - 1) +
              Time_Interval.Time_Offset as Start_Date_Time,
            Time_Table.Valid_From +
              Time_Table.Duration * (numbers.num - 1) +
              Time_Interval.Time_Offset +
              Time_Interval.Duration as End_Date_Time,
            Time_Interval.duration as Duration
       from Time_Table cross join numbers
         inner join Time_Interval using(Time_table_Id)
     )
   select Hierarchy_Group_Id,
          Time_Table_Id,
          Start_Date_Time,
          End_Date_Time,
          Duration
    from all_interval
    where trunc(Start_Date_Time) <= Valid_To;


Следующее представление добавляет к интервалам каждого узла
иерархии интервалы для родительских узлов.

create or replace view V_All_Unrolled_Interval
as
select V_Hierarchy.Hierarchy_Group_Id,
       V_Hierarchy.Priority,
       V_Unrolled_Interval.Time_Table_Id,
       V_Unrolled_Interval.Start_Date_Time,
       V_Unrolled_Interval.End_Date_Time,
       V_Unrolled_Interval.Duration
  from V_Hierarchy inner join V_Unrolled_Interval
    on V_Hierarchy.Participating_Hier_Group_Id = V_Unrolled_Interval.Hierarchy_Group_Id;


Наконец, самое сложное — комбинирование интервалов с разными
приоритетами.

create or replace view v_combined_interval
as
with
  -- Select all DISTINCT start/end points of all intervals
  all_point as (
    select Hierarchy_Group_Id,
           start_date_time as date_time
      from V_All_Unrolled_Interval
    union
    select Hierarchy_Group_Id,
           end_date_time as date_time
      from V_All_Unrolled_Interval),
  -- Generate sequence of all intervals between consecutive points
  all_interval0 as (
    select Hierarchy_Group_Id,
           date_time as start_date_time,
           lead(date_time) over (partition by Hierarchy_Group_Id order by date_time) as end_date_time
      from all_point
  ),
  -- Remove the last interval with end_date_time is null
  all_interval as (
    select Hierarchy_Group_Id,
           start_date_time,
           end_date_Time
      from all_interval0
      where end_Date_time is not null
  ),
  -- Split all intervals
  split_interval as (
    select V_All_Unrolled_Interval.Hierarchy_Group_Id,
           V_All_Unrolled_Interval.priority,
           all_interval.start_date_time,
           all_interval.end_date_time
      from V_All_Unrolled_Interval cross join all_interval
      where V_All_Unrolled_Interval.Hierarchy_Group_Id = All_Interval.Hierarchy_Group_Id
        and All_Interval.start_date_Time >= V_All_Unrolled_Interval.start_date_Time
        and All_Interval.start_date_Time < V_All_Unrolled_Interval.end_date_Time
  )
  -- Select only intervals with highest priority (= lowest priority value).
  select Hierarchy_Group_Id,
         min(priority) as priority,
         start_date_Time,
         end_date_Time
    from split_interval
    group by Hierarchy_Group_Id, start_date_Time, end_date_time;


Немного пояснений.

Результат представления V_All_Unrolled_Interval
(для одного дня и для Hierarchy_Group_Id = 3)

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1 +-----+                                         +--------+     +--+

2          +-----+              +--------+        +-----+     +--------+

3                   +-----+  +-----+  +-----+     +--+


Результат промежуточного запроса All_Point — все начала и концы
всех интервалов:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

  +     +  +     +  +     +  +  +  +  +  +  +     +  +  +  +  +  +  +  +


Результат промежуточного запроса All_Interval — все интервалы между
всеми последующими точками:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

  +-----+--+-----+--+-----+--+--+--+--+--+--+-----+--+--+--+--+--+--+--+


Результат промежуточного запроса Split_Interval — все исходные интервалы,
разбитые на меньшие интервалы, определяемые точками из результата
запроса ALL_POINT:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1 +-----+                                         +--+--+--+     +--+

2          +-----+              +--+--+--+        +--+--+     +--+--+--+

3                   +-----+  +--+--+  +--+--+     +--+


Результат представления V_Combined_Interval — из всех перекрывающихся
интервалов выбраны интервалы с самым большим приоритетом:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1 +-----+                                         +--+--+--+     +--+

2          +-----+              +--+--+--+                    +--+  +--+

3                   +-----+  +--+        +--+


Наконец, интервалы, примыкающие друг к другу, "cклеиваются" при помощи
представления V_Interval:

create or replace view V_Interval
as
with time_int2 as (
  select Hierarchy_Group_Id,
         Priority,
         Start_Date_Time,
         End_Date_Time,
         case when lag(End_Date_Time) Over(Partition by Hierarchy_Group_Id, Priority order by Start_Date_Time) = Start_Date_Time then 0
              else 1
        end as flag
    from V_Combined_Interval
),
time_int3 as (
  select Hierarchy_Group_Id,
         Priority,
         Start_Date_Time,
         End_Date_Time,
         sum(flag) over(Partition by Hierarchy_Group_Id, Priority order by Start_Date_Time) as Interval_Group
    from time_int2
)
select Hierarchy_Group_Id,
       Priority,
       interval_group,
       min(Start_Date_Time) as Start_Date_Time,
       max(End_Date_Time) as End_Date_Time
  from time_Int3
  group by Hierarchy_Group_Id, Priority, Interval_Group;


В результате получаем:

  0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
  |--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|--|

1 +-----+                                         +--------+     +--+

2          +-----+              +--------+                    +--+  +--+

3                   +-----+  +--+        +--+


На этом пока все.
Re[20]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 25.11.08 10:36
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

Вы золотой человек! Спасибо Вам огромное!
Re[20]: Сложно-алгоритмо-фобия
От: __kain Россия  
Дата: 28.11.08 07:26
Оценка:
Здравствуйте, Flying Dutchman, Вы писали:

FD>Скрипты находятся здесь.


Ссылка не работает. Вы не могли бы еще раз выложить?..

P.S.
Читаю ваши скрипты и просвещаюсь
Re[21]: Сложно-алгоритмо-фобия
От: Flying Dutchman Украина  
Дата: 28.11.08 08:33
Оценка:
Здравствуйте, __kain, Вы писали:

__>Здравствуйте, Flying Dutchman, Вы писали:


FD>>Скрипты находятся здесь.


__>Ссылка не работает. Вы не могли бы еще раз выложить?..


__>P.S.

__>Читаю ваши скрипты и просвещаюсь

Ссылка уже работает. Желаю успеха.
Re[4]: Сложно-алгоритмо-фобия
От: MasterZiv СССР  
Дата: 29.11.08 18:21
Оценка: :)
__kain пишет:
> На данный момент, я перерабатываю систему учета посещаемости студентов
> ВУЗа (пишу заново). Данные для оценки посещений получаются

Что ж тут сложного в алгоритмах-то ?
примитив.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Сложно-алгоритмо-фобия
От: VGn Россия http://vassilsanych.livejournal.com
Дата: 05.12.08 11:50
Оценка:
Здравствуйте, __kain, Вы писали:

__>2 Flying Dutchman

>> В твоем случае структура базы довольно сложная, тем более что используются темпоральные данные, так что этому надо уделить особое внимание.
__>Структуру я весь диплом проектировал, и потом еще месяц =) Она получилась универсальной и вроде более-менее простой, но, действительно, наличие темпоральных данных только усложняет дело. Причем все эти данные могут потом еще и перегенерироваться (полностью и частично)... Я тут подумал, нужно наверное в структуру еще что-то добавить, чтобы в коде нужно было проводить меньше вычислений.

Для темпоральных данных иногда подходят materialized view.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Re[7]: Сложно-алгоритмо-фобия
От: VGn Россия http://vassilsanych.livejournal.com
Дата: 05.12.08 11:50
Оценка:
__>Кстати, а что вы думаете на счет объектных возможностей Oracle? Может с помощью них получится нормально сделать?

Объектами назвать это сложно, но коллекции этих самых объектов вполне удобны для переноса больших объемов данных между процедурами. Значительно улучшается повторное использование и структура кода.
Минус — оптимизации тут как бы не при делах, поэтому злоупотреблять не стоит.
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.