Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.05.2010, 14:27   #1
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию Запрос возвращает пустую таблицу, если один из подзаросов возвращает пустую таблицу

Запросы в SQL Access.

Схематично запрос выглядит так:
Код:
SELECT [S3].material.name, [S1].OstatokPrih-[S2].OstatokRash As OstatokPrihNach, [S3].OstatokPrih-[S4].OstatokRash As OstatokPrihKonec
FROM
(здесь идет запрос на формирование данных через SELECT, идет ограничение по  первой дате и группировка, вычисляется сумма) as [S1],
(такой же принцип, только для расхода) as [S2], 
(также, только по второй дате) as [S3],
(запрос для расхода) as [S4]

WHERE

 ([S3].material.код_материала=[S4].material.код_материала)
В каждом из подзапросов используется одни и теже таблицы.

Смысл этого запроса в том, чтобы сделать вычисления Остатка расхода до первой даты(OstatokPrihNach) и до второй даты (OstatokPrihKonec).

В чем проблема:
Запрос работает только, если OstatokPrihNach возвращает какие-либо значения. Но если дата указана до того периода, когда не было каких-либо расходов, то в данном подзапросе таблица пустая и в самом основном запросе она тоже становится пустой.
А надо чтобы в данных полях отображался бы 0, и показывались поля OstatokPrihKonec.
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Старый 11.05.2010, 14:45   #2
SunKnight
Участник клуба Подтвердите свой е-майл
 
Аватар для SunKnight
 
Регистрация: 14.12.2007
Сообщений: 1,434
По умолчанию

Так сложно ответить в чем проблема.
Возможно это происходит по тому, что если поле пусто (NULL) его нельзя вычесть из числа, по этому и результат (OstatokPrihNach) у вас пуст.
Проповедую design patterns, верую в MVC, доверяю eXtrime programming.
SunKnight вне форума Ответить с цитированием
Старый 11.05.2010, 14:53   #3
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию

Цитата:
Возможно это происходит по тому, что если поле пусто (NULL) его нельзя вычесть из числа, по этому и результат (OstatokPrihNach) у вас пуст
Подумал тоже, что в этом проблема, но даже если не указывать в выборке [S1].OstatokPrih-[S2].OstatokRash As OstatokPrihNach, а указать только в FROM эти подзапросы (в котором S1 возвращает пустой запрос), то все равно в общем результате возвращает пустой результат.
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Старый 11.05.2010, 16:11   #4
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

гыгы
больше похоже на пятничную задачу - что нужно писать в подселекте, чтобы наверху появились нуллы

нет данных - вот и нулл
если есть в акссессе функа NVL(a, b) [если первый параметр нулловый, то вернет то что указано во втором параметре] или что-то подобное, то заюзать ее, если нет, то можно и case-ом обойтись
soleil@mmc вне форума Ответить с цитированием
Старый 12.05.2010, 11:53   #5
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию

Цитата:
если есть в акссессе функа NVL(a, b) [если первый параметр нулловый, то вернет то что указано во втором параметре] или что-то подобное, то заюзать ее, если нет, то можно и case-ом обойтись
В Аксессе для этих целей используется как я понял функция iif ('выражение', 'значение для true', 'значение для false')
Но все равно мне трудно понять как это может помочь.

Рассмотрим простой пример:
Предположим, есть три связанные таблицы material (kodmaterial, name) и Prihod (kol, stoimost, kodPrih, kodmaterial, kodprihod) и PrihodDop(kodprihod, dateprihod). Связь между ними один ко многим (material.kodmaterial=Prihod.kodmat erial) and (Prihod.kodprihod=PrihodDop.kodprih od). То есть для каждого материала есть запись его количества и стоимости и даты прихода.

Задача в том, чтобы вывести сумму количества материала за определенный период.
Например, если пишем такой запрос:
Код:
SELECT material.name, material.kodmaterial, SUM (Prihod.kol) as PrihodKol 
FROM (material INNER JOIN Prihod ON material.kodmaterial = Prihod.kodmaterial) INNER JOIN PPRRIIXXOODD ON Prihod.kodPrihod = PrihodDop.kodPrihod
WHERE ((Int([PrihodDop].[dateprihod])>=#3/11/2009#) and (Int([PrihodDop].[datePrihod])<=#2/15/2010#) )

Group by material.name, material.kodmaterial
То в этом случае выводятся только материалы у которых дата прихода попадает в данный промежуток.
Например:
Код:
name       kol
material1  30
material2  25
А надо, чтобы для других материалов значения были нулевыми, то есть так:

Код:
name       kol
material1  30
material2  25
material3  0
material4  0
Не могу понять как в вышеописанном запросе это сделать, или где так вставить функцию iif, чтобы выводило как надо.
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Старый 12.05.2010, 12:08   #6
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

вот это уже понятнее
а то какие-то сферические запросы в вакууме

тебе нужно использовать внешнее объединение таблиц ака left outer join той таблицы, в которой данных может не быть
а IIF() применять для суммы в таком виде
Код:
sum(iif(Prihod.kol is null, 0, Prihod.kol))
soleil@mmc вне форума Ответить с цитированием
Старый 12.05.2010, 13:09   #7
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию

Пробовал писать запрос так:

Код:
SELECT material.name, material.kodmaterial, sum(iif(Prihod.kol is null, 0, Prihod.kol)) as PrihodKol 
FROM (material LEFT OUTER JOIN Prihod ON material.kodmaterial = Prihod.kodmaterial) LEFT OUTER JOIN PPRRIIXXOODD ON Prihod.kodPrihod = PrihodDop.kodPrihod
WHERE ((Int([PrihodDop].[dateprihod])>=#3/11/2009#) and (Int([PrihodDop].[datePrihod])<=#2/15/2010#) )

Group by material.name, material.kodmaterial
но при этом все равно ничего не меняется, также возвращает только те материалы, которы входят в условия даты.

Пробовал менять LEFT на RIGHT и с комбинацией INNER, либо ничего не меняется либо выводит ошибку синтаксиса.

На FULL OUTER JOIN и UNION JOIN Access Jet SQL пишет ошибку синтаксиса, может как-то по другому происходит включение из обеих таблиц.

Пробовал просто для двух таблиц material и Prihod сделать соединение по LEFT OUTER JOIN, но все равно выводит как для LEFT INNER JOIN.

В чем у меня ошибка?
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Старый 12.05.2010, 13:27   #8
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию

P.S. Делаю в Access 2007 (формат Access 2002-2003).
По справке вроде поддерживает OUTER:
http://office.microsoft.com/en-us/ac...345551033.aspx
Пробовал и и через дизайнер запросов в Access менять тип связи, все равно выводит одно и тоже.
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Старый 12.05.2010, 14:24   #9
soleil@mmc
SQL-коддинг
Участник клуба
 
Регистрация: 16.01.2009
Сообщений: 1,192
По умолчанию

1) и чего? чтобы хранить дату прихода по айтему - нужна прям отдельная таблица?! или там все-таки побольше полей?!

2) почему у тебя в запросе одна таблица, а в связке другая?
Код:
JOIN PPRRIIXXOODD ON Prihod.kodPrihod = PrihodDop.kodPrihod
3) ну и более детально рассмотрев твою задачу, решил тебе предложить переписать запрос на такой
Код:
SELECT 
   m.name, 
  (здесь идет запрос на формирование данных через SELECT, идет ограничение по  первой дате и группировка, вычисляется сумма) OstatokPrih_begin,
  (такой же принцип, только для расхода) OstatokRash_begin,
  (также, только по второй дате) OstatokPrih_end,
  (запрос для расхода) OstatokRash_end
FROM material m
а уже внутри подзапросов прикручиваешь везде iif() чтобы сумма по кол-ву была как минимум 0
soleil@mmc вне форума Ответить с цитированием
Старый 12.05.2010, 15:40   #10
ArtInt
Форумчанин
 
Аватар для ArtInt
 
Регистрация: 06.03.2009
Сообщений: 583
По умолчанию

to soleil@mmc:
1) Там побольше полей, плюс потом к этой таблице PrihodDop там потом таблица со складом привязана. Я бы конечно соединил таблицу Prihod и PrihodDop, но изначально в таком утвержденном виде дали таблицу. Вдруг надо будет чтобы для каждого количества материала по определенной стоимости есть своя дата поступления?

2) В моих таблицах поля неудобо читаемы (не я создавал), поэтому заменил их в примере на другие.
Код:
FROM (material LEFT OUTER JOIN Prihod ON material.kodmaterial = Prihod.kodmaterial) LEFT OUTER JOIN PrihodDop ON Prihod.kodPrihod = PrihodDop.kodPrihod
3) Сейчас уже переписал, хоть и очень громоздко, но работает, через UNION (таблица значений удовлетворяющей условию и таблица значений не удовлетворяющей условиям (там эти поля 0)) для каждого вычисления, а потом снова UNION этих таблиц.

Схема предложенная тобой тоже возникала у меня в мозгу, но постоянно запутывался в реализации. Попробую попозже написать по твоей схеме.
Не стыдно чего-то не знать, стыдно не стремиться к знаниям.
ArtInt вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Удалить пустую строку из ListView Shouldercannon Общие вопросы Delphi 2 28.04.2010 16:02
Вернуть пустую ячейку Ruben Microsoft Office Excel 3 05.02.2010 16:20
Копирование данных на первую пустую ячейку kzld Microsoft Office Excel 8 15.07.2009 14:06
если поле Patr пусто или null то пустую строку возвращает azat БД в Delphi 5 01.02.2008 13:05
как удалить пустую страницу? Gambler Microsoft Office Word 1 29.10.2006 20:57