Форум: "Базы";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
ВнизКак застраховаться от нулевых вложенных запросов? Найти похожие ветки
← →
Boroda Oleg (2004-06-30 21:39) [0]Если при написании запроса используются вложенные запросы, то иногда случается ситуация, когда вложеный запрос выдает пустое значение (возможно NULL), и расчет дальше не идет. Возможно ли как-то застраховаться от этого нуля.
Подробнее:
Имеем таблицу Table. В ней поля: ID, DOLG
Имеем таблицу OPLATA. В ней поля: ID_table, SUMM
Значения ID и ID_TABLE - цедые, DOLG и SUMM - с точкой.
Понятно, что оплат по одной строчке может быть много. Поэтому строим запрос:
SELECT T.DOLG
(SELECT SUM(OP.SUMM) FROM OPLATA OP
WHERE (OP.ID_TABLE = T.ID)) S_OPL,
T.DOLG-
(SELECT SUM(OP.SUMM) FROM OPLATA OP
WHERE (OP.ID_TABLE = T.ID)) OSTATOK
FROM TABLE T
Если имеется хотя-бы одна оплата, значения S_OPL и OSTATOK считаются правильно. Если нет ни одной оплаты, оба они пусты (хотя, по идее OSTATOK должен быть равен DOLG). Как с этим бороться?
И еще, вдогонку. Если мы, предположим, имеем два поля DOLG1 и DOLG2 - как научить SQL понимать выражение:
Если DOLG2 = 0, то результат = DOLG1
иначе результат = DOLG2
← →
P.N.P. © (2004-06-30 22:06) [1]Можно UDF написать с проверкой значений,
или готовую взять где-нибудь
← →
Fay © (2004-06-30 22:35) [2]fb15 + coalesce
← →
Vemer © (2004-07-01 00:53) [3]Сделай ХП с проверкой по COUNT..
← →
Boroda Oleg (2004-07-01 09:32) [4]У меня тоже мысли насчет процедуры или функции... Только вот, хоть убей, не помню, как ее в SQL засунуть. Народ, подскажите, плис формат.
← →
Johnmen © (2004-07-01 09:35) [5]Наиболее "дешёвый" вариант с дополнительными бонусами - перейти на FB1.5
← →
Desdechado © (2004-07-01 10:33) [6]чтобы NULL превратить в 0, используй функцию из UDF-библиотеки RFunc
← →
Boroda Oleg (2004-07-01 11:17) [7]ЛЮДИ!!!!
Как эту дурную процедуру или функцию вызвать в SQL запросе ???
← →
Johnmen © (2004-07-01 11:18) [8]Какую функцию ?
← →
Boroda Oleg (2004-07-01 11:28) [9]Любую. Как составить запрос так, чтобы в нем вызвать функцию?
Имеется процедура MyProcedure(A : integer):integer
(как точно писать не знаю, пишу как в Дельфе)
Нужно вызвать ее в SQL запросе, что-то типа:
SELECT ID, NAME, DOLG,
MyProcedure(DOLG) OSTATOK, ...
^^^^^^^^^^^^^^^^^
какой формат вызова правильный? У меня на MyProcedure плюется как на заразу.
И еще, если возвращаются 2 цифры, как это писать нужно (в смысле вызывать).
← →
asp © (2004-07-01 11:33) [10]Boroda Oleg (30.06.04 21:39) > СУБД?
← →
Johnmen © (2004-07-01 11:36) [11]>Boroda Oleg (01.07.04 11:28) [9]
>Имеется процедура MyProcedure(A : integer):integer
Может это ф-ия всё-таки ?
И где она имеется ?
И вообще на ibase.ru ходил ?
← →
Boroda oleg (2004-07-01 11:55) [12]>> Имеется процедура MyProcedure(A : integer):integer
> Может это ф-ия всё-таки ?
> И где она имеется ?
> И вообще на ibase.ru ходил ?
Процедура. Сам я ее нарисовал.
На ibase.ru счас пойду, только что там искать....
← →
Johnmen © (2004-07-01 11:57) [13]>Процедура. Сам я ее нарисовал.
:)
Процедура, возвращающая значение, обычно называется функцией...
Где ты ее нарисовал ?
← →
Соловьев © (2004-07-01 11:59) [14]
> Имеется процедура MyProcedure(A : integer):integer
хранимая?
← →
kaif © (2004-07-01 12:36) [15]Вообще-то, ИМХО, не стоит так организовывать сами таблицы.
Нормальная система учата платежей бывает устроена иначе, например, так:
ID OP_DATE PLATELSCHIK DEBIT CREDIT
=============================================
1 "01.01.2004" 113 1000 0 //начисление долга
2 "05.01.2004" 113 0 200 //платеж
3 "05.01.2004" 113 0 100 //платеж
4 "05.01.2004" 113 0 500 //платеж
Тогда если нужно узнать, сколько кто должен, делается простой запрос:
SELECT PLATELSCHIK, SUM(DEBIT - CREDIT) DOLG
FROM TABLE1
GROUP BY PLATELSCHIK
И никаких проблем с NULL и т.п. вещами.
С уважением.
← →
Boroda Oleg (2004-07-01 12:38) [16]Господа!!!
Дошел сам.
Процедура вызывается:
SELECT OPLAT FROM MyProcedure (ID)
Вот блин!!
← →
Boroda Oleg (2004-07-01 12:42) [17]2 kaif
У меня задача несколько иная: учет должников.
Т.е. у каждого есть некий долг. И, по идее, этот долг должен гаситься - или одной суммой, или частями (что реально происходит чаще). Поэтому сам долг - в первой таблице, а опаты - во второй.
← →
kaif © (2004-07-01 12:51) [18]2 Boroda Oleg
А что, то, что я написал, разве это не учет должников?
А теперь скажи, что получится при твоем подходе и при том, что я показал, если чел задолжал 1000, а потом заплатил 600, а потом задолжал еще 1000 и потом разом заплатил 1400. В моей таблице после запроса его долг будет равен ровно 0. А в твоей системе таблиц как учесть такие 4 операции?
← →
kaif © (2004-07-01 12:57) [19]И еще с чего ты взял, что бывают только должники? А если кто-то предоплатил что-то? Тогда что, будешь ему в таблицу долгов "минус" писать, а в таблицу "оплат" писать отгрузку ему "товара/услуги"? Чем начисление долга отличается от начисления платежа, чтобы видеть в этом отношение один-ко-многим? Только потому что "как правило" платят частями? Но вот простой пример, что я привел:
1000
600
1000
1400
-----------
0
Где здесь можно один-ко-многим углядеть?
И "одного такого случая" достаточно.
Хотя, как говорится, дело хозяйское...
← →
kaif © (2004-07-01 13:01) [20]Самое интересное произойдет в твоей системе при "предоплате". Представим себе физиономию клиента, которому отказали в предоплате, мотивировав это нарушением внешнего ключа в 2 таблицах. Типа "если угодно с нами работать, будьте добры стать должником". Предоплату не принимаем.
← →
Boroda Oleg (2004-07-01 13:44) [21]Опять ты не так понял.
Ведется учет ТОЛЬКО ДОЛЖНИКОВ.
Если человек расплатился, он из программы либо вообще удаляется, либо каким-то образом блокируется. Даже если он переплатил, то разбираться с ним будет его менеджер.
Вообще - цель программы - учет дебиторской задолженности. Дебитором клиент становится только если он не расплатился в рамках договорных обязательств.
← →
TohaNik © (2004-07-01 13:56) [22]>Если человек расплатился, он из программы либо вообще удаляется, либо каким-то образом блокируется. Даже если он переплатил, то разбираться с ним будет его менеджер.
Рекет какойто:))
← →
Boroda oleg (2004-07-01 15:09) [23]Люди, а как все-таки два или больше значения получить при вызове хранимой процедуры из SQL запроса? У меня в процедуре вернуться должно 2 значения. При выполнении:
SELECT OPLAT FROM MyProcedure (ID)
выдается, естественно 1 значение. Сколько я не пытался воткнуть возле OPLAT еще оду переменную - SQL редактор плюется как на бешенного. Как до нее добраться то?
← →
Dazhan (2004-07-01 17:02) [24]Зечем вести учет ТОЛЬКО ДЕБИТОРОВ в двух таблицах с геморройем, когда можно вести учет ВСЕХ ЧУВАКОВ в одной таблице без геморойя?
Если же нужны ТОЛЬКО ДОЛЖНИКИ, то получать их детским запросом:
SELECT SUM(DEBIT-CREDIT), PLATELSCHIK
FROM TABLE1
GROUP BY PLATELSCHIK
HAVING SUM(DEBIT-CREDIT) > 0
Если слова DEBIT CREDIT пугают, то для понятности можно их назвать: POPAL и ZAPLATIL
:)
← →
stud © (2004-07-01 17:12) [25]можно и в двух таблицах вести, а у каждого клиента добавить поле баланс например, который будет автоматически изменяться в зависимости от операции (платеж или услуги) и не надо никаких процедур и объединений таблиц. все одним запросом из одной таблицы и клиент и его долг - не долг
← →
Boroda Oleg (2004-07-01 17:17) [26]Оно конечно хорошо, но только в случае, если мне кто-то платит каждый день по 1 000 р. (при сумме долга в 1 000 000), то у меня только на этого должника возникнет 1 000 записей. Хотя сейчас и веники по 200 Гиг держат, но с такими тратами скоро и их не хватит. :))
Люди, и подскажите кто, если знает, как все-таки два или больше значения получить при вызове хранимой процедуры из SQL запроса? Подробнее расписал чуть выше.
← →
stud © (2004-07-01 17:20) [27]так создай в ней два выходных параметра
← →
stud © (2004-07-01 17:21) [28]begin
select1 ...... into par1
select2 ...... into par2
suspend;
end
← →
Boroda oleg (2004-07-01 19:07) [29]Угу. Так я и сделал (не совсем так, но похоже).
Как теперь это в SQL запрос вставить?
SELECT DB.ID_DEBIT, DB.CHECKED, DB.COLOR, DB.OTDEL, DB.KLIENT,
(SELECT OSTAT FROM getostatok (DB.ID_DEBIT)) OSTATOK,
(SELECT DOLG FROM getdolg (DB.ID_DEBIT)) REALDOLG
^^^^^^^^^^^^^^ - вот сюда
FROM DEBIT DB, OTDEL OT, KLIENT KL
WHERE (OT.id_otdel = DB.otdel)
AND (KL.id_klient = DB.klient)
У меня сейчас 2 процедуры, но делают они одно практически и то же. Я пытался свести в одну процедуру, и она при отладке выдает оба параматра. Но как вставить их в SQL запрос, чтобы одной коммандой их получить оттуда - увы, не смог.
← →
stud © (2004-07-02 09:19) [30]так как обычная процедура выбора вызывается
select * from my_proc(param....) [order by...]
← →
Rutven © (2004-07-02 14:56) [31]
> Оно конечно хорошо, но только в случае, если мне кто-то
> платит каждый день по 1 000 р. (при сумме долга в 1 000
> 000), то у меня только на этого должника возникнет 1 000
> записей.
Так эта 1000 записей у тебя будет в любом случае :)
← →
stud © (2004-07-02 15:10) [32]по-моему проще написать ону процедуру, возвращающую необходимый набор и вызывать только ее, а не извращаться с запросами
← →
Boroda Oleg (2004-07-02 16:28) [33]2 Rutven: "Жирность" базы где хранятся сами задолженности - 24 поля, имеются строки по 50 символов.
"Жирность" базы с оплатами - 4 поля из них одна строка10, дата, целое и decimal15,2
Что больше весит?
2stud: Спасибо! Как я сам не догадался...
А насчет процедуры - оно может и грамотней так будет. Действительно, возможностей на порядок больше. Хотя запросы как-то привычнее...
← →
Petr V.Abramov (2004-07-03 00:49) [34]> Опять ты не так понял.
> Ведется учет ТОЛЬКО ДОЛЖНИКОВ.
А если будет (неявная) возможность вести и учет переплат, вам надают по шее???
Вы уперлись в частную задачу, и нарвались на геморрой (причем именно от непонимания задачи общей), с которым 33 поста люди бьются. kaif © предложил Вам решение общей задачи и без геморроя.
Совет: послушайте kaif ©
> Ведется учет ТОЛЬКО ДОЛЖНИКОВ.
> то разбираться с ним будет его менеджер.
У фирмы, на которую Вы работаете, есть два магазина: в центре Москвы и у кольцевой дороги вокруг Урюпинска. Соответствующий менеджер убеждает Вас, что цены в этих магазинах одинаковы, всегда были одинаковы и будут одинаковы вечно.
Вы должны понимать, что в этом случае вечность может закончиться через неделю, и если
цены в магазинах не будут выравниваться системой автоматически до окончания вечности;
цены в магазинах не смогут стать разными сразу после ее окончания,
то Вы спроектировали систему плохо.
(с) "Записки автоматизатора"
P.S. "Застраховаться от этого нуля" можно, испольуя
table left join oplata
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.07.25;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.034 c