Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

А что если SUM(Table.Field) = null? [IB6.x]


Страницы:   1 2

KIR ©   (2003-10-14 11:48:00) 

Народ, ситуация следующая: требуется сделать так:

SELECT
SUM(TABLE1.FIELD)+SUM(TABLE2.FIELD) AS TOTALSUM
FROM
TABLE1 LEFT OUTER JOIN TABLE2
ON TABLE1.ID = TABLE2.TABLE1ID

В некоторых строках получается, что SUM(TABLE2.FIELD) = NULL, тогда и SUM(TABLE1.FIELD)+SUM(TABLE2.FIELD)тоже получается равной null, а надо чтоб было SUM(TABLE1.FIELD). Причем, если сделать так:

SELECT
SUM(TABLE1.FIELD) AS SUM1,
SUM(TABLE2.FIELD) AS SUM2
FROM
TABLE1 LEFT OUTER JOIN TABLE2
ON TABLE1.ID = TABLE2.TABLE1ID

то все нормально, но два поля, а нодо все в одно...


SasaR   (2003-10-15 15:11:00) [1]

Я имел ввиду не UDF а обычную сохранённую процедуру :)))


KIR   (2003-10-15 14:45:00) [2]

>SasaR (14.10.03 16:41) [23] но, насколько мне известно, IB не позволяет создавать UDF с NULL-параметрами...


KIR   (2003-10-14 17:30:00) [3]

Народ, всем спасибо! В итоге я все сделал через ХП (спасибо Romkin © (14.10.03 12:30) [9] за идею). Решил делать через ХП, потому что то, что я выложил в форум - только небольшая часть запроса - в реальности все гораздо сложнее.


Vlad   (2003-10-14 17:13:00) [4]

Думаю, тут самый лучший выход - [23]
Аналог функции NVL в Оракле.


MsGuns   (2003-10-14 17:11:00) [5]

>kaif © (14.10.03 16:32) [22]

Я написал "мучиться", имея в виду доп. фрикции с датасетом в дизайне. Мне кажется, что в событии проще и, что немаловажно, нагляднеепоказать алгоритм преобразования данных для отображения.

С неменьшим уважением ;))


SasaR   (2003-10-14 16:41:00) [6]

Написать SP типа is_null(val1,val2)
----------
select (is_null(SUM(XXX),0)).....


kaif   (2003-10-14 16:32:00) [7]

MsGuns © (14.10.03 15:15) [21]
Если рез-т нужен для отображения, то идея kaif © (14.10.03 15:08) [19] , только можно не мучиться с калькулируемыми полями, а просто использовать событие OnGetText


Дело вкуса, однако...

Можно не мучиться с событиями OnGetText, а просто использовать вычисляемое поле. :)
Тем более, что у вычисляемого поля есть преимущество: его можно не только отображать, но и обращаться потом к нему с целью получения данных (например, при генерации отчета) так же, как и к обычному полю.
Я лично редко использую OnGetText (только когда нужно как-то нетривиально форматировать информацию). Хотя, возможно, я и не прав.
С уважением, kaif


MsGuns   (2003-10-14 15:15:00) [8]

Если рез-т нужен для отображения, то идея kaif © (14.10.03 15:08) [19] , только можно не мучиться с калькулируемыми полями, а просто использовать событие OnGetText любого из суммовых полей, происывая туда результат сложения, заменяя отсутствующие суммы нулями процедурно.


kaif   (2003-10-14 15:09:00) [9]

Пардон:
with DataSet do
FieldsByName("SUM3").AsCurrency :=
FieldsByName("SUM1").AsCurrency +
FieldsByName("SUM2").AsCurrency;


kaif   (2003-10-14 15:08:00) [10]

Судя по вопросу, нужно получить более, чем 1 запись и отобразить в гриде.
Я бы сделал очень просто.
Сделал бы второй (из приведенных) запрос:

SELECT
SUM(TABLE1.FIELD) AS SUM1,
SUM(TABLE2.FIELD) AS SUM2
FROM
TABLE1 LEFT OUTER JOIN TABLE2
ON TABLE1.ID = TABLE2.TABLE1ID

создал бы в приложении persistent поля у датасета и добавил бы еще вычисляемое поле SUM3 в датасет.
(Поле типа ftCalculated).
И написал бы в обработчик OnCalcField:

with DataSet do
FieldsByName("SUM1").AsCurrency :=
FieldsByName("SUM2").AsCurrency +
FieldsByName("SUM3").AsCurrency;

И хотя я большой любитель написания ХП (Johnmen не даст соврать :), я в данном случае обошелся бы без них.


Romkin   (2003-10-14 14:49:00) [11]

Исправляюсь: вызов select sum(FullSum) as TotalSum from List_Full_sum
^)))))


Romkin   (2003-10-14 14:47:00) [12]

Ой!!!! млин...


Johnmen   (2003-10-14 14:46:00) [13]

Как не накопительная ?
В запросе явно видно, что ожидается одна запись...:)


Romkin   (2003-10-14 14:24:00) [14]

Зачем? Сумма вроде не накопительная, я чисто перевел select. А зачем suspend в конце? Если ничего нет - ничего и не вернет


Johnmen   (2003-10-14 14:22:00) [15]

>Romkin © (14.10.03 14:01)

Забыл проинициализировать FullSum нулевым значением и
FullSum = FullSum + FIELD1 + FIELD2;
да и suspend нужен в самом конце, вне циклов (если хотим select"ом из процедуры).


Romkin   (2003-10-14 14:01:00) [16]

Вот пример: имеем

SELECT
SUM(TABLE1.FIELD)+SUM(TABLE2.FIELD) AS TOTALSUM
FROM
TABLE1 LEFT OUTER JOIN TABLE2
ON TABLE1.ID = TABLE2.TABLE1ID


Надо, чтобы NULL == 0, делаем

create procedure List_Full_sum
returns (FullSun <FieldType>)
as
declare variable FIELD2 <FiELDTYPE>;
declare variable ID <FiELDTYPE>;
begin
for select ID, FIELD
from Table1
into :ID, :FullSum
do begin
if (FullSum is NULL) then FullSum = 0;
FIELD2 = NULL;
/* Если TABLE1ID - с уникальным индексом */
select FIELD2 from Table2
where TABLE1ID = :ID
into :FIELD2;
if (FIELD2 is NULL) then
FIELD2 = 0;
FullSum = FullSum + FIELD2;
suspend;
end
end

Если с TABLE1ID может быть много записей - тоже не проблема

create procedure List_Full_sum
returns (FullSun <FieldType>)
as
declare variable FIELD1 <FiELDTYPE>;
declare variable FIELD2 <FiELDTYPE>;
declare variable ID <FiELDTYPE>;
begin
for select ID, FIELD
from Table1
into :ID, :FIELD1
do begin
if (FIELD1 is NULL) then
FIELD1 = 0;
/* Если TABLE1ID - не является ключем */
for select FIELD2 from Table2
where TABLE1ID = :ID
into :FIELD2
do begin
if (FIELD2 is NULL) then
FIELD2 = 0;
FullSum = FIELD1 + FIELD2;
suspend;
end
end
end

ТАк понятно?
Вызов, ессно, элементарен:
select * from List_Full_sum


Danilka   (2003-10-14 13:49:00) [17]

[11] KIR © (14.10.03 13:47)
1. ХП может возвращать НД
2. Если на клиенте, то проще и правильнее (на мой взгляд) сделать вычисляемое поле, чем, все тащить в стрингГрид.


KIR   (2003-10-14 13:47:00) [18]

Я решил задачу так: вывожу итоговый НД не в DBGrid"e а в стандартном TStringGrid"e (сделал процедуру FormGrid и в ней все обрабатываю). Единственный косячок - TStringGrid внешне немного отличается от TDBGrid"a, ну и, естественно, пропала возможность использовать FIBPlus"овскую Master-Detail связку. Приходится открывать DetailDS по SelectCell StringGrid"a...

Простите, что не догоняю, но как в моем случае мне поможет ХП? Мне требуется вернуть НД и отобразить его в DBGrid"e...


Johnmen   (2003-10-14 12:41:00) [19]

>Romkin © (14.10.03 12:30)

Да, тоже хороший вариант :)
И в данном случае, пожалуй, самый приемлемый.


Romkin   (2003-10-14 12:30:00) [20]

2Johnmen 3. Написать ХП и не мучится


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо