Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Составление сложного запроса к БД 
:(
    Опции темы
AntonPavlov
Дата 8.6.2014, 21:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 28.5.2010

Репутация: нет
Всего: нет



Доброго времени суток! 
Помогите, пожалуйста решить следующую проблему. 
Есть три таблицы: 

Income[id, Sdate, id_elem, amount] (приход деталей, содержит инфо о приходящих на склад деталях, из таблицы Nomenclature, за определенную дату, в определенном количестве), 
Outgo[id, Sdate, id_elem, amount] (расход деталей, содержит инфо о расходованных деталях, из таблицы Nomenclature, за определенную дату, в определенном количестве),
Nomenclature[id, name_elem] (справочник деталей). 

Необходимо выбрать наименование детали, дата расхода, когда расходованное количество превысило имеющееся количество деталей. Упорядочить по наименованию детали и дате расхода. 
Пытаюсь делать так: 
а) Создаем представление, которое возвращает разность между количеством каждой когда-либо израсходованной запчасти, и количеством этой же когда-либо пришедшей на склад запчасти:    
Код

CREATE VIEW OutMinusInc AS 
select outgo.sdate, nomenclature.id, 
sum(outgo.amount)-sum(income.amount) AS delta 
FROM outgo JOIN nomenclature ON 
outgo.id_elem=nomenclature.id 
JOIN income ON 
income.id_elem=nomenclature.id 
group by outgo.sdate, nomenclature.id;


b) Выводим название запчасти и дату расхода, учитывая, что разность, возвращаемая представлением OutMinusInc, должна быть больше нуля: 

Код

SELECT name_elem, outgo.sdate 
FROM outgo JOIN nomenclature ON 
outgo.id_elem=nomenclature.id 
JOIN income ON 
income.id_elem=nomenclature.id 
JOIN OutMinusInc ON 
nomenclature.id=OutMinusInc.id 
WHERE delta>0
GROUP BY outgo.sdate,name_elem 
ORDER BY name_elem, outgo.sdate;


Это работает не верно. Из за того, что происходит группировка по датам (в пункте а), получается неверный результат. Без группировки по дате запрос не работает. Как избавиться от группировки и получить верный результат? 
PM MAIL   Вверх
Akina
Дата 8.6.2014, 22:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Нормализуйте данные - избавьтесь от 2 идентичных таблиц, держите всё в одной (расход - отрицательное количество, например).
Тогда достаточно тривиального запроса, считающего нарастающий итог.

Цитата(AntonPavlov @  8.6.2014,  22:47 Найти цитируемый пост)
Пытаюсь делать так

Подход содержит внутреннюю ошибку - не учитывается порядок обработки данных.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
password
Дата 9.6.2014, 00:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 23.9.2008
Где: Украина, Сумы

Репутация: 3
Всего: 8



Не написали какая база данных.

Цитата

Нормализуйте данные - избавьтесь от 2 идентичных таблиц, держите всё в одной

Или добавьте в таблицу Outgo поле с таблицы Income.id (с какого прихода взята деталь.)

Можно так же написать тригер на расход, который не позволит снимать детали больше чем есть на складе.

По поводу вашего sql мои наброски (не проверял, может и не работать)
Код

select a.id_elem, z.name_elem, a.Sdate, a.amount
from Outgo a
inner join (select id_elem, sum(amount) as amount from Outgo group by id_elem) cur1 on cur1.id_elem=a.id_elem
inner join (select id_elem, sum(amount) as amount from Income group by id_elem) cur2 on cur2.id_elem=a.id_elem
left join Nomenclature z on z.id_elem=a.id_elem
where cur1.amount>cur2.amount and exists 
  (select 1 from 
     (select sum(dd.amount) as amount from Outgo dd where a.id_elem=dd.id_elem and a.Sdate>=dd.Sdate) dd1
   where cur2.amount<dd1.amount)
order by z.name_elem, a.Sdate


Это сообщение отредактировал(а) password - 10.6.2014, 10:35
PM MAIL Skype   Вверх
AntonPavlov
Дата 11.6.2014, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 28.5.2010

Репутация: нет
Всего: нет



password, спасибо большое за помощь!
НО! Этот запрос тоже работает не совсем корректно. 
Проблема в том, что в случае (ниже - примерная иллюстрация, описывающая неподходящую ситуацию):
Код

Дата     Приход     Расход    Запчасть
1.06      1               10           1
2.06      20              2            1

ничего не выведется!
То есть: в случае, если сумма пришедших за все даты запчастей "покрывает" сумму ушедших за все даты запчастей, запрос работает не верно, что иллюстрирует таблица выше. 

Это сообщение отредактировал(а) AntonPavlov - 11.6.2014, 16:07
PM MAIL   Вверх
password
Дата 11.6.2014, 21:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 23.9.2008
Где: Украина, Сумы

Репутация: 3
Всего: 8



Тогда попробуйте как то так:
Код

select a.id_elem, z.name_elem, a.Sdate, a.amount
from Outgo a
left join Nomenclature z on z.id_elem=a.id_elem
where exists 
  (select 1 from 
     (select sum(dd.amount) as amount from Outgo dd where a.id_elem=dd.id_elem  and a.Sdate>=dd.Sdate) s,
     (select sum(dd1.amount) as amount from Income dd1 where a.id_elem=dd1.id_elem and a.Sdate>=dd1.Sdate) s1
   where s.amount>s1.amount)
order by z.name_elem, a.Sdate


P.S. еще раз акцентирую внимание на том что нужно добавить в таблицу Outgo поле Income.id, чтобы привязать из какого прихода взята деталь, для упрощения таких выборок и недопущения таких случаев.

Это сообщение отредактировал(а) password - 11.6.2014, 21:19
PM MAIL Skype   Вверх
AntonPavlov
Дата 11.6.2014, 22:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 28.5.2010

Репутация: нет
Всего: нет



Спасибо еще раз, попробую чуть позже!!
А что значит 
Код

select 1 

?
Насчет добавления поля Income.id - я понял, но, дело в том, что эта вся муть - курсовик. 
Структура БД уже утверждена, и, в связи с упоротостью и полной неадекватностью преподавателя, вносить изменения в структуру будет уже теперь крайне проблематично. 
PM MAIL   Вверх
password
Дата 11.6.2014, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 76
Регистрация: 23.9.2008
Где: Украина, Сумы

Репутация: 3
Всего: 8



Код

...
exists 
  (select 1 from
...


В данном случае нам не важно какое значение в селекте, а важно что выполняется условие в exists
EXISTS
PM MAIL Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0683 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.