Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.07.25;
Скачать: CL | DM;

Вниз

Как застраховаться от нулевых вложенных запросов?   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.035 c
14-1089057319
ANNIHILATOR
2004-07-05 23:55
2004.07.25
Когда разваляться штаты?


3-1088578752
Zlod3y
2004-06-30 10:59
2004.07.25
ODBC


6-1085649280
Nlo
2004-05-27 13:14
2004.07.25
Share


14-1088752863
МТС-ник
2004-07-02 11:21
2004.07.25
unlimited GPRS


1-1089787776
belkova
2004-07-14 10:49
2004.07.25
Размер формы