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

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

SUM -> NULL [D5, Paradox]


Страницы:   1 2

PKT ©   (2002-12-26 04:59:00) 

Запрос:
select SUM(CREDIT) - SUM(DEBET) from ...
Если у всех записей, например, поле DEBET пустое,
то на выходе вместо суммы CREDIT минус нульвозвращается
пустое значение.

Сейчас делаю отдельно запрос SUM(CREDIT), отдельно
SUM(DEBET), проверяю их на if not NULL и нахожу разницу.

А можно ли все-таки одним запросом ?


diMAN   (2003-01-04 17:09:00) [1]

> Johnmen © (04.01.03 12:56)
> Последние уточнения по поводу P.S. :
> Где, при помощи чего создана таблица ?
> Где, при помощи чего выполнен запрос ?
> Где, при помощи чего видны результаты ?

Все действия сделаны при помощи Database Desktop (таблица Paradox).


Johnmen   (2003-01-04 12:56:00) [2]

>diMAN © (04.01.03 12:41)

Последние уточнения по поводу P.S. :
Где, при помощи чего создана таблица ?
Где, при помощи чего выполнен запрос ?
Где, при помощи чего видны результаты ?


diMAN   (2003-01-04 12:41:00) [3]

> Johnmen © (31.12.02 10:47)
> Почему же ? Кто указывает, что NULL ?

На это указывает то, как получаются таблицы prihodbefore.db, prihodbetween.db и т.д.


...
SQL.Clear;
SQL.Add("SELECT A.OrgCode, SUM(A.SummaWithNalog) Prihod FROM "opermain.db" A");
SQL.Add("WHERE A.CodeOper=1 AND A.DateOper < "" + DateToStr(WorkDateStart) + """);
SQL.Add("GROUP BY A.OrgCode");
Open;
DbiMakePermanent(handle, PChar(DataBaseTDir + "prihodbefore.db"), true);
Close;
SQL.Clear;
SQL.Add("SELECT A.OrgCode, SUM(A.SummaWithNalog) Prihod FROM "opermain.db" A");
SQL.Add("WHERE A.CodeOper=1 AND A.DateOper BETWEEN "" + DateToStr(WorkDateStart) + "" AND "" + DateToStr(WorkDateEnd) + """);
SQL.Add("GROUP BY A.OrgCode");
Open;
DbiMakePermanent(handle, PChar(DataBaseTDir + "prihodbetween.db"), true);
Close;
...


Таким образом мы вернулись к сути вопроса, что если в течение рабочего периода у организации не было прихода, то она не попадёт в таблицу "prihodbetween.db", а следовательно при объединении LEFT OUTER JOIN, поле C.Prihod (см. предыдущий пример) будет NULL. В чём я давно и легко убедился, открыв полученную таблицу через Database Desktop. Собственно это и побудило меня найти способ преобразования в SQL-запросе значения NULL в 0, что и было успешно достигнуто. Рабочий вариант запроса я и предложил автору вопроса.

P.S. Только что я создал таблицу с полями Code: ftAutoinc, Summa: ftMoney и добавил в неё пять записей, у которых поле Summa содержит NULL. Выполнил запрос SELECT SUM(Summa) FROM test, получив в результате NULL и выполнил запрос SELECT SUM(CAST("0"||CAST(Summa AS CHAR(30)) AS MONEY)) FROM test, получив в рузультате 0. Если Вы и на этот раз сомневаетесь, то проверьте собственноручно.


Johnmen   (2002-12-31 10:47:00) [4]

>diMAN © (31.12.02 10:35)

Вывод однозначен - NULL реализован как нулевое значение, а это не одно и то же ! (в данном конкретном случае)

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

Почему же ? Кто указывает, что NULL ?


diMAN   (2002-12-31 10:35:00) [5]

>Johnmen © (30.12.02 17:39)
> То есть ты хочешь сказать, что есть поля (C.Prihod, D.Vernut, > F.Oplata), в которых значение NULL ? И, кстати, каковы типы
> этих полей ?

Да, именно это я и хочу сказать. Все эти поля типа ftCurrency. В них находятся сведения о суммах прихода товара, возврата товара, оплаты за товар по каждой из организаций за определённый период времени (любой - хоть 1 день, хоть 1 месяц, хоть 1 год). И естественно, за данный период конкретная оргганизация могла не получать (возвращать, оплачивать) товар, т.е. значения этих полей будут NULL.

> Delirium^.Tremens © (30.12.02 16:50)
> Да, круть, нафиг. После приклейки нуля больше всего мне
> понравилось : LEFT OUTER JOIN. Видимо на "LEFT RIGHT OUTER
> INNER JOIN" BDE уже ругнулся.

Я в этом ничего страшного не вижу. Я понимаю что слово OUTER можно ставить, а можно - и нет. Но мне так удобнее и нагляднее. Я привык делать так. К тому же в Local SQL Help -> OUTER join (файл localsql.hlp) в примерах дается именно такой (полный) вариант записи SQL-запроса.


Johnmen   (2002-12-30 17:39:00) [6]

>diMAN © (30.12.02 16:46)

То есть ты хочешь сказать, что есть поля (C.Prihod, D.Vernut, F.Oplata), в которых значение NULL ? И, кстати, каковы типы этих полей ?



Delirium^.Tremens   (2002-12-30 16:50:00) [7]

Да, круть, нафиг. После приклейки нуля больше всего мне понравилось : LEFT OUTER JOIN. Видимо на "LEFT RIGHT OUTER INNER JOIN" BDE уже ругнулся.


diMAN   (2002-12-30 16:46:00) [8]

> Johnmen © (27.12.02 11:10)
> Где выполняется запрос ? Как выполняется ? Какой движок
> используется ?

Например, в моей программе. Всегда корректно 100% (через TQuery). D5, D6 + BDE + Paradox.

Вот работающий у меня фрагмент:

Screen.Cursor := crHourGlass;
with WorkQuery do
try
SQL.Clear;
SQL.Add("SELECT A.ShortName OrgName, CAST(""0""||CAST(B.Prihod AS CHAR(30)) AS MONEY) Prihod1, ");
SQL.Add("CAST(""0""||CAST(C.Prihod AS CHAR(30)) AS MONEY) Prihod2, ");
SQL.Add("CAST(""0""||CAST(D.Vernut AS CHAR(30)) AS MONEY) Vernut1, ");
SQL.Add("CAST(""0""||CAST(E.Vernut AS CHAR(30)) AS MONEY) Vernut2, ");
SQL.Add("CAST(""0""||CAST(F.Oplata AS CHAR(30)) AS MONEY) Oplata1, ");
SQL.Add("CAST(""0""||CAST(G.Oplata AS CHAR(30)) AS MONEY) Oplata2");
SQL.Add("FROM "org.db" A LEFT OUTER JOIN "prihodbefore.db" B ON A.Code=B.OrgCode");
SQL.Add("LEFT OUTER JOIN "prihodbetween.db" C ON A.Code=C.OrgCode");
SQL.Add("LEFT OUTER JOIN "vernutbefore.db" D ON A.Code=D.OrgCode");
SQL.Add("LEFT OUTER JOIN "vernutbetween.db" E ON A.Code=E.OrgCode");
SQL.Add("LEFT OUTER JOIN "oplatabefore.db" F ON A.Code=F.OrgCode");
SQL.Add("LEFT OUTER JOIN "oplatabetween.db" G ON A.Code=G.OrgCode");
SQL.Add("WHERE A.ID=1");
SQL.Add("ORDER BY A.ShortName");
Open;
DbiMakePermanent(handle, PChar(DataBaseTDir + "postavsvod.db"), true);
Close;
except
Screen.Cursor := crDefault;
ShowMessage("Ошибка!");
end;


Anatoly Podgoretsky   (2002-12-27 13:26:00) [9]

Lady D © (27.12.02 09:45)
Есть делание - предикакт ALL является предикатом по умолчанию [ALL]


petr_v_a   (2002-12-27 13:16:00) [10]

> Lady D © (27.12.02 09:45)
> Проблема в том, что написала об этом Lady...
По Вашему участию в других дискуссиях у меня, по крайней мере, сложилось впечатление, что Ваш уровень гораздо выше среднего уровня участников форума, НО: Вас опять подвело "невнимательное читание писанины" и Вы, как бы это при девушках сказать, к сожалению, лажанулсь :)
sum(all column_value) по синтаксису Local SQL эквивалентно
sum( column_value)
А девушек у нас любят, берегут, и уважают :), рискну выразить мнение подавляющего большинства участников форума :)

По сути вопроса: null в результате sum(column_value) получается, либо когда не просуммировано ни одной строки, либо когда суммируются только null`ы. Так как в Local SQL нет ф-ции типа nvl(nullable_expr,expr), которая в случае, если nullable_expr is null возвращала бы expr, в противном - ниче не трогала, прав Sergey13 © (27.12.02 11:42) - даже если Вы победите данный конкретный запрос, null`ы гадить Вам будут каждый день до скончания века


Sergey13   (2002-12-27 11:42:00) [11]

Господа, а вам не кажется, что вы идете не тем путем. Не проще ли будет добавить в таблицы на эти поля дефолтное значение 0, и проапдейтить существующие записи
update table set debit=0 where debit is null
update table set credit=0 where credit is null

И все!!! Все будет работать правильно. Работа на 5 минут. Я бы сделал именно так.


Johnmen   (2002-12-27 11:10:00) [12]

>diMAN © (27.12.02 11:01)

По поводу 100% :
Где выполняется запрос ? Как выполняется ? Какой движок используется ?


diMAN   (2002-12-27 11:01:00) [13]

> Johnmen © (26.12.02 11:23)
> Где работает ?

> Val © (26.12.02 11:29)
> Где работает ?
> подозреваю, что нигде.

> MsGuns © (26.12.02 11:48)
> В Local SQL, я думаю, работать будет.

Вы вопрос внимательно читали
SUM -> NULL [D5, Paradox]
^^^^^^^
Естественно, что в Local SQL. И говоря что это будет 100% работать, я не лукавил, т.к. данный код у меня уже более трёх лет с успехом работает. А кто не верит - проверьте, а уже потом говорите что нигде не будет работать.


Johnmen   (2002-12-27 10:26:00) [14]

>Lady D © (27.12.02 09:45)

Маша, у Вас просто какая-то юношеская горячность...:)))
см. ЮЮ © (27.12.02 09:54)


passm   (2002-12-27 10:00:00) [15]

ЮЮ © (27.12.02 09:54)> Верно сказано насчет тождественности.
.-ALL------.
>>-SUM--(----+----------+--expression--)-----------------------><
"-DISTINCT-"


ЮЮ   (2002-12-27 09:54:00) [16]

О чём? Подчитать то подсчитает, но если в одном стодбце нет ни одной записи со значением не NULL, то и SUMM() вернет NULL и пезультат будет NULL независимо от суммы по второму столбцу.
а SELECT SUM(ALL credit) - SUM(ALL debit) FROM ... ТОЖДЕСТВЕНЕН авторскому select SUM(CREDIT) - SUM(DEBET) from ...


Lady D   (2002-12-27 09:45:00) [17]

Похоже опять никто не понял (или сделал вид), что я дала "короткое" и верное решение. Lady D © (26.12.02 13:28).
Включение ключей в аггрегатные функции может избавить от многих головных болей. Например, мне нужно выдать отчет по клиентам с суммой продаж и вычислением Profit по каждому. Естественно, должен быть и итог с такими же полями. Нет проблем если каждый из клиентов покупал в этот отрезок времени, а если нет? Его показатели пусты, а COUNT его посчитает. Как же быть с итогом? Очень просто: COUNT(ALL saldo) подсчитает всех, у кого сумма NOT NULL... COUNT(DISTINCT saldo) подсчитает все уникальные saldo(не знаю зачем это здесь, но тем не менее). То же самое справедливо и для SUM,AVG... Проблема в том, что написала об этом Lady и ни у кого не хватит духа сказать: да, ты права, я об этом читал, но давно забыл. Напротив, каждый здесь ждет случая (подходящего и не очень) чтобы попестовать меня. Итак, решение:

SELECT SUM( ALLcredit) - SUM( ALLdebit) FROM ...

Есть сегодня желающие поспорить?


MsGuns   (2002-12-26 19:40:00) [18]

>petr_v_a © (26.12.02 16:44)
> Искусство программирования - в том, чтоб не влезть в дурацкий проект :))

Это искусство называется "дипломатией". У настоящих программеров, как правило, начисто отсутствует 8))


petr_v_a   (2002-12-26 16:44:00) [19]

Искусство программирования - в том, чтоб не влезть в дурацкий проект :))
Честно, ничей конкретно не имел в виду :))


-=Sergeante=-   (2002-12-26 15:03:00) [20]


> MsGuns © (26.12.02 11:48)
> А если база уже есть, создана n лет назад, содержит полмиллиона
> записей и успешно юзается m-м кол-вом персонала ?
> Искусство программирования заключается не только в том,
> как проектировать НОВЫЕ проекты, но и как выкручиваться
> в старых, не так ли ?


О! Здравая мысль.


Страницы:   1 2

Наверх

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