Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.10.2009, 11:50   #1
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию Изменить данные

Добрый день!

База Firebird 2.0
Имеется таблица KLIENT_UCHET cо следующими полями:
KEY_KLIENT_UCHET Integer
DATE_1 DATE
DATE_2 DATE
KEY_KLIENT Integer
KEY_USLUGI Integer
TYPE_UCHET Integer

DATE_1 - начало периода, DATE_2 - конец периода

Нужно сделать тригер, чтобы при созданиии новой записи автоматически проставился конец периода для предыдущего значения для этого же клиента и услуги (KEY_KLIENT и KEY_USLUGI), то есть максимальная дата до текущей даты. Я так предполагаю, что должно быть что-то типа этого:

Код:
update klient_uchet set DATA_2 = new.data_1 - 1 where (max(data_1) < new.data_1) and KEY_KLIENT = NEW.KEY_KLIENT and KEY_USLUGI = NEW.KEY_USLUGI;
Но естественно это не работает :-(

Получается ошибка:

Код:
Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Invalid aggregate reference.
Подскажите, пожалуйста, что делать?
SlavaSH вне форума Ответить с цитированием
Старый 22.10.2009, 12:26   #2
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

ваще-то не очень хорошая идея
в некоторых субд можно нарваться на мутатинг

и что ты будешь делать если вставят запись между уже существующими для одного и того же KEY_KLIENT, KEY_USLUG?

если по установленным бизнес-правилам дата_2 предыдущей д.б. на день меньше дата_1 следующей, то может имеет смысл вообще отказаться от второй границы и получать ее в селекте?
soleil@mmc вне форума Ответить с цитированием
Старый 22.10.2009, 12:46   #3
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию

Цитата:
Сообщение от soleil@mmc Посмотреть сообщение
ваще-то не очень хорошая идея
в некоторых субд можно нарваться на мутатинг

и что ты будешь делать если вставят запись между уже существующими для одного и того же KEY_KLIENT, KEY_USLUG?

если по установленным бизнес-правилам дата_2 предыдущей д.б. на день меньше дата_1 следующей, то может имеет смысл вообще отказаться от второй границы и получать ее в селекте?
знаю, что не очень хорошая идея, но в противном случае у меня просто невероятный геморой получается: очень сложные запросы приходится строить, чтобы выяснить интервалы, в которых TYPE_UCHET принимает значение, например, 1. У меня как раз сейчас и есть одна дата, но я уже второй день долблюсь с выборкой интервалов и понял, что вторая дата невероятно упростит мне задачу: мне всего один простецкий запрос сделать и всё.

Что делать, если вставят запись между уже существующими для одного и того же KEY_KLIENT, KEY_USLUGI?

Этот вариант тоже учесть надо.

В этом случае точно так же у предыдущей записи должно прописаться DATE_2 = NEW.DATE_1 - 1, а у текущей записи NEW.DATE_2 = ???

Эту дату тоже найти надо. Здесь она будет минимальная после текущей (new.data_1)

Так как это можно организовать?

И еще вопросик... а что такое мутанинг?
SlavaSH вне форума Ответить с цитированием
Старый 22.10.2009, 12:53   #4
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

Цитата:
Сообщение от SlavaSH Посмотреть сообщение
И еще вопросик... а что такое мутанинг?
мутатинг - это когда ты через триггер запускаешь бесконечный цикл обновления таблицы самой себя
к примеру триггер на before_update запускает апдейт той же самой таблицы и так далее по циклу

а чтобы не долбиться с выборками - можно написать селективную ХП
в принципе, на оракле такой запрос довольно просто строится с использованием аналитических фунок
Код:
with
  klient_uchet as (
  select 10 key_klient_uchet, 1 key_uslugi, 1021 key_klient, to_date('01.09.2009', 'DD.MM.YYYY') data, 0 type_uchet from dual union all
  select 10, 1, 1021, to_date('05.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 20, 1, 1021, to_date('03.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 20, 1, 1021, to_date('05.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 20, 1, 1021, to_date('07.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 30, 2, 1021, to_date('05.09.2009', 'DD.MM.YYYY'), 3 from dual union all
  select 40, 2, 1021, to_date('01.09.2009', 'DD.MM.YYYY'), 4 from dual union all
  select 50, 3, 1021, to_date('03.09.2009', 'DD.MM.YYYY'), 5 from dual union all
  select 50, 3, 1021, to_date('04.09.2009', 'DD.MM.YYYY'), 5 from dual union all
  select 60, 3, 1021, to_date('06.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 70, 4, 1021, to_date('07.09.2009', 'DD.MM.YYYY'), 0 from dual union all
  select 80, 4, 1021, to_date('09.09.2009', 'DD.MM.YYYY'), 2 from dual union all
  select 90, 5, 1021, to_date('30.09.2009', 'DD.MM.YYYY'), 0 from dual union all
  select 100, 5, 1021, to_date('23.09.2009', 'DD.MM.YYYY'), 1 from dual union all
  select 110, 4, 1021, to_date('13.09.2009', 'DD.MM.YYYY'), 3 from dual union all
  select 120, 3, 1021, to_date('05.09.2009', 'DD.MM.YYYY'), 2 from dual
  )

select 
  ku.*,
  lead(ku.data) over(partition by ku.key_klient_uchet, ku.key_uslugi order by ku.data) data_2
from klient_uchet ku
key_klient_uchet key_uslugi key_klient data type_uchet
10 1 1021 01.09.2009 0 05.09.2009
10 1 1021 05.09.2009 2
20 1 1021 03.09.2009 2 05.09.2009
20 1 1021 05.09.2009 2 07.09.2009
20 1 1021 07.09.2009 2
30 2 1021 05.09.2009 3
40 2 1021 01.09.2009 4
50 3 1021 03.09.2009 5 04.09.2009
50 3 1021 04.09.2009 5
60 3 1021 06.09.2009 2
70 4 1021 07.09.2009 0
80 4 1021 09.09.2009 2
90 5 1021 30.09.2009 0
100 5 1021 23.09.2009 1
110 4 1021 13.09.2009 3
120 3 1021 05.09.2009 2

если в ФБ есть любая функа для нумерования набора данных, то можно и по-другому реализовать

Последний раз редактировалось soleil@mmc; 22.10.2009 в 13:05.
soleil@mmc вне форума Ответить с цитированием
Старый 22.10.2009, 13:01   #5
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию

Цитата:
Сообщение от soleil@mmc Посмотреть сообщение
мутатинг - это когда ты через триггер запускаешь бесконечный цикл обновления таблицы самой себя
к примеру триггер на before_update запускает апдейт той же самой таблицы и так далее по циклу
понятно... но здесь такое не получится....

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

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

Для двух дат у меня запрос такой:

Код:
select date_1,date_2 from KLIENT_UCHET where data_2 >= :DATA and KEY_KLIENT = :KEY_KLIENT and KEY_USLUGI = :KEY_USLUGI
SlavaSH вне форума Ответить с цитированием
Старый 22.10.2009, 13:09   #6
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию

Цитата:
Сообщение от soleil@mmc Посмотреть сообщение
Код:
select 
  ku.*,
  lead(ku.data) over(partition by ku.key_klient_uchet, ku.key_uslugi order by ku.data) data_2
from klient_uchet ku
идея понятна, но FireBird не понимает слова lead, over, partition
SlavaSH вне форума Ответить с цитированием
Старый 22.10.2009, 13:12   #7
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

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

просто тяжело иметь такой головняк с поддержкой целостности границ периодов если есть возможность все сделать через запрос
soleil@mmc вне форума Ответить с цитированием
Старый 22.10.2009, 13:19   #8
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию

Цитата:
Сообщение от soleil@mmc Посмотреть сообщение
я там выше пост подправил
не факт что запрос будет точно такой же
но имхо если получится запросом получить данные, то дальше из этого набора отобрать с учетом фильтра не составит никаких проблем

просто тяжело иметь такой головняк с поддержкой целостности границ периодов если есть возможность все сделать через запрос
согласен, но как сделать этот запрос для FireBird? в этом то у меня и проблема.... уже второй день долблюсь... поэтому решил, что лучше добавить вторую дату, так запрос строится элементарно... но само собой от этого получилось тоже много проблем... я в ауте короче!
SlavaSH вне форума Ответить с цитированием
Старый 22.10.2009, 13:42   #9
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

какая точно версия ФБ?
soleil@mmc вне форума Ответить с цитированием
Старый 22.10.2009, 13:47   #10
SlavaSH
Форумчанин
 
Регистрация: 12.08.2008
Сообщений: 174
По умолчанию

Цитата:
Сообщение от soleil@mmc Посмотреть сообщение
какая точно версия ФБ?
FireBird 2.0
SlavaSH вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Изменить данные в базе SlavaSH БД в Delphi 10 13.08.2009 14:32
Изменить иконку xakkkkker Общие вопросы Delphi 2 23.08.2008 19:40
Изменить размеры Манжосов Денис :) Gamedev - cоздание игр: Unity, OpenGL, DirectX 2 16.05.2008 20:14
Не могу изменить данные в DB aleksey_prm Помощь студентам 1 17.03.2008 08:21
изменить логин ERASERROR О форуме и сайтах клуба 5 23.02.2008 08:11