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

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

Access, ADO [D7, Access, ADO]


Е. ©   (2006-01-14 09:39:00) 

Есть таблица [ОбъемРабот] с полями:

[КодЦеха] - Длинное целое
[КодРаботы] - Длинное целое
[Январь] - Одинарное с плавающей точкой
[Февраль] - Одинарное с плавающей точкой
...
[Декабрь] - Одинарное с плавающей точкой.

Месяца в таблице обозначают объем данной работы КодРаботы), выполненной данным цехом(КодЦеха) в данном месяце.

Необходимо подсчитать суммарный объем по каждой работе за год всего предприятия. Я делаю запрос:

SELECT
 SUM(Январь+Февраль+...+Декабрь) AS [Объем],
 КодРаботы
FROM
 ОбъемРабот
GROUP BY
 КодРаботы;

и получаю неправильный результат (некоторые значения равны нулю). В справке MS Access сказано, что "Функция Sum пропускает записи с полями, содержащим значения Null". Если дело в этом, то каким образом можно это обойти? Или запрос составлен неверно?


sniknik   (2006-01-15 13:32:00) [1]

> ...но работает почему-то только непосредственно в Access.
т.к. это функция самого приложения (Application), а не jet (он только встроенный бейсик может использовать, но не функции описаные в разных "левых" программах)

иллюстрация
unit AccessAppUnit;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, AccessXP, ComObj;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Button2: TButton;
   Label1: TLabel;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   TestNull: OleVariant;
 public
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 TestNull:= Null;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 appAccess: _Application;
begin
 appAccess:= CreateComObject(CLASS_AccessApplication) as _Application;
 try
   Label1.Caption:= appAccess.Nz(TestNull, 'NULL');
 finally
   appAccess:= nil;
 end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 TestNull:= 'NOT NULL';
end;

end.


Е.   (2006-01-15 11:12:00) [2]

Нашлась некая функция Nz в MS Access, с ней запрос выглядит "красивее и понятнее":

SELECT
 SUM(Nz(Январь)+Nz(Февраль)+..+Nz(Декабрь)) AS Объем,
 КодРаботы
FROM
 ОбъемРабот
GROUP BY КодРаботы;

...но работает почему-то только непосредственно в Access. Если использовать через ADOQuery.Sql выдает ошибку: "Неопределенная функция 'Nz' в выражении." Почему?


sniknik   (2006-01-14 13:09:00) [3]

Anatoly Podgoretsky ©   (14.01.06 12:51) [10]
> Это не важно, даже в пределах одной записи результат будет NULL если хотя бы одно из полей NULL
так именно это я и сказал... сумма в "линейку" дает Null ...
но т.к. в [6]/[8] рассматривался второй вариант (SUM([Январь])+SUM([Февраль])+...) то тут сначала складываются "столбики" и до строки Null "дойдет" только если весь столбец из Null. (в "столбиках" Null просто пропускается)

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

p.s. ктото когото не понял...


Anatoly Podgoretsky   (2006-01-14 12:51:00) [4]

sniknik ©   (14.01.06 10:48) [6]
sniknik ©   (14.01.06 11:01) [8]

Это не важно, даже в пределах одной записи результат будет NULL если хотя бы одно из полей NULL
Только первый вариант даст нужный результат, преобразование NULL в 0

Е.   (14.01.06 10:37) [4]
А ты столбиком запиши, будет и красиво и понятно.


Е.   (2006-01-14 11:09:00) [5]


> sniknik ©   (14.01.06 11:01) [8]
> а понял. у тебя же там группировка, т.е. SUM-мируются небольшие
> группы значений, и наверное попадает что вся группа по какомуто
> месяцу из значений Null ... тогда и вся сумма Null и сложение
> сумм где есть хоть одна с Null даст Null ...
>  
> "неправильный результат" это пропуски да? (пустые значения).
>  если да то все верно, и второй тебе не подойдет.


Да именно так. Еще раз спасибо.


sniknik   (2006-01-14 11:01:00) [6]

а понял. у тебя же там группировка, т.е. SUM-мируются небольшие группы значений, и наверное попадает что вся группа по какомуто месяцу из значений Null ... тогда и вся сумма Null и сложение сумм где есть хоть одна с Null даст Null ...
 
"неправильный результат" это пропуски да? (пустые значения). если да то все верно, и второй тебе не подойдет.


sniknik   (2006-01-14 10:51:00) [7]

> Интересно, функция SUM везде так странно работает или только в MS Access?
это не SUM это правила Null -> 1 +  Null = Null (и вообще любое число + Null)
будет везде аналогично, правда с исключениями... (в MSSQL например это поведение настраиваемо, по умолчанию также (на тех установках mssql что я делал))


sniknik   (2006-01-14 10:48:00) [8]

> Тот же результат во втором варианте.
по идее не должно
приведи второй вариант полностью, как ты его написал.


Е.   (2006-01-14 10:45:00) [9]

Интересно, функция SUM везде так странно работает или только в MS Access?


Е.   (2006-01-14 10:37:00) [10]

А вот первый вариант работает, правда несколько громоздко выглядит, но работает. Спасибо.
PS. Остается ощущение, что можно как-то упростить. Или нет?


Е.   (2006-01-14 10:09:00) [11]

Тот же результат во втором варианте.


Е.   (2006-01-14 10:08:00) [12]

Тот же результат.


sniknik   (2006-01-14 09:50:00) [13]

> Если дело в этом, то каким образом можно это обойти?
SUM(iif(IsNull([Январь]),0,[Январь])+...)
или
SUM([Январь])+SUM([Февраль])+...


Наверх

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