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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 23.04.2016, 04:43   #1
delphi159
Подтвердите свой е-майл
 
Регистрация: 27.01.2015
Сообщений: 28
По умолчанию Не могу создать запрос для посчитания остатков склада (объединять 2 запроса)

На Firebird 2.5 server в БД есть таблицы: goods, income, sale.
Goods: goods_id, name
Income: Income_id, Goods_id, incomeqty (quantity), recdate
Sale: sales_id,income_id,Goods_id,saleqty ,recdate

Есть такой запрос,который выбирает приходы,расходы и разницу во временном интервале:
Код:
SELECT g.name, g.goods_id, 
       coalesce(dt2.sum_income,0), 
	   coalesce(dt2.sum_sales,0),
       coalesce(dt2.differ_between,0)
FROM goods g
LEFT JOIN
(SELECT goods_id,
   sum(sum_income) as sum_income,
   sum(sum_sale) as sum_sale,
   sum(sum_income - sum_sale) as differ_between
 from (select goods_id, sum(incomeqty) as sum_income, 0 as sum_sale, 'income' as which
      from income
      where income.recdate between :d1 and :d2         
      group by goods_id
    union all
      select goods_id, 0, sum(salesqty), 'sale'
      from sales
      where sale.recdate between :d1 and :d2 
      group by goods_id) dt1
 group by goods_id
) dt2 on g.goods_id = dt2.goods_id
Но я хочу в нём добавить стартовые остатки,чтобы получать конечные остатки товара на момент времены.
стартовые остатки до конкретной времены =sum(прыходы)-sum(расходы).
Конечные остатки на момент времены=стартовые остатки+прыходы в интервале-расходы в интервале.
стартовые остатки по-моему должны получиться так:
Код:
select income.goods_id, sum(incomeqty) as start_income, 0 as start_sale, 'income' as which
            from income
            where income.recdate < :d1
            group by goods_id
          union all
            select goods_id,0, sum(saleqty) as start_sale,0, 'sale'
            from sale
            where sale.recdate < :d1
            group by goods_id
         group by goods_id
Где и как включить в главном запросе запрос получения стартовых остатков?
delphi159 вне форума Ответить с цитированием
Старый 23.04.2016, 08:39   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

В одном запросе сумму до и сумму после можно так получить
Код:
SELECT goods_id,
    SUM(CASE WHEN recdate<:d1 THEN sum_income ELSE 0 END) AS sum_saleIN,
    SUM(CASE WHEN recdate>=:d1 THEN sum_income ELSE 0 END) AS sum_sale
  FROM income
  WHERE recdate<=:d2
  GROUP BY goods_id
Аналогично для расхода. Был бы приход и расход в одной таблице все стало бы гораздо проще

PS

В огнептице case может чуть по другому, не помню
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию

Последний раз редактировалось Аватар; 23.04.2016 в 08:44.
Аватар вне форума Ответить с цитированием
Старый 24.04.2016, 18:28   #3
delphi159
Подтвердите свой е-майл
 
Регистрация: 27.01.2015
Сообщений: 28
Печаль

Аватар, переделал запрос,но почему-то конечные остатки неправильно получаю(endqnt): 5000+1000-20-5=6000?

Код:
SELECT
    G.Name,
    G.Doods_id,
    coalesce(dt2.startqnt,0) as startqnt,      
    coalesce(dt2.income,0)as income, 
    coalesce(dt2.sales,0)as sales,
    coalesce(dt2.writeoff,0)as writeoff,
    coalesce(dt2.endqnt,0) as endqnt
FROM Goods G
LEFT JOIN
(select                                                                            --dt2
     Pr_k,
     sum(startincome) as startincome,                                                           --приходы до 
     sum(startsale) as startsale,                                                                    --продажи до
     sum(startwriteoff) as startwriteoff,                                                         --списывание до
     sum(income) as income,                                                                        --приходы в интервале  
     sum(sale) as sales,                                                                               --продажи в интервале 
     sum(writeoff) as writeoff,                                                                       --списывание в интервале 
     sum(startincome-startsale-startwriteoff) as startqnt,                                --остатки стартовые 
     sum(startincome-startsale-startwriteoff+income-sale-writeoff) as endqnt    --конечные остатки
from(                                                                       
     
   select  i.goods_id,
           sum(case when i.recdate<'01/01/2010' then i.incomeqty end) as startincome,
           0 as startsale,
           0 as startwriteoff,                         --списывание товара
           sum(case when i.recdate between '01/01/2010'  and '01/01/2020' then i.incomeqty end) as income,
           0 as sale,
           0 as writeoff,
           'income' as which
    from income i
    where i.recdate <='01/01/2020'
    group by goods_id

  union all

    select
           s.goods_id,
           0,
           sum(case when s.recdate<'01/01/2010' then s.saleqty end) as startsale,
           0,
           0,
           sum(case when s.recdate between '01/01/2010' and '01/01/2020' then s.saleqty end) as sale,
           0,
           'sale'
    from sale s
    where s.recdate <= '01/01/2020'
    group by goods_id
 
 union all

    select
           w. goods_id,
           0, 
           0,
           sum(case when w.writeoffDate<'01/01/2010' then w.writeoffQty end) as startwriteoff,
           0,
           0,
           sum(case when w.writeoffDate between '01/01/2010' and '01/01/2020' then w.writeoffQty end) as writeoff,
           'writeoff'
    from writeoff w
    where w.writeofDate < '01/01/2020'
    group by goods_id) dt1
 group by Goods_id )dt2
 on G.Goods_id=dt2.Goods_id
Derived Table DT1 и конечный запрос дают такой результат:
Изображения
Тип файла: jpg recs.jpg (96.7 Кб, 87 просмотров)
delphi159 вне форума Ответить с цитированием
Старый 24.04.2016, 18:56   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

А где dt2.Goods_id ?
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 24.04.2016, 19:33   #5
delphi159
Подтвердите свой е-майл
 
Регистрация: 27.01.2015
Сообщений: 28
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
А где dt2.Goods_id ?
Если вы о рисунке, тогда где "ID" написано (в БД оны по-другому называются).
delphi159 вне форума Ответить с цитированием
Старый 24.04.2016, 19:48   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Я о запросе. В подзапросе с псевдонимом dt2 нет поля Goods_id. Как тогда быть с on G.Goods_id=dt2.Goods_id ?
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 24.04.2016, 19:53   #7
delphi159
Подтвердите свой е-майл
 
Регистрация: 27.01.2015
Сообщений: 28
Радость

Цитата:
Сообщение от Аватар Посмотреть сообщение
Я о запросе. В подзапросе с псевдонимом dt2 нет поля Goods_id. Как тогда быть с on G.Goods_id=dt2.Goods_id ?
Извините, где pr_K написано это и есть Goods_id.
delphi159 вне форума Ответить с цитированием
Старый 24.04.2016, 20:34   #8
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Код:
     sum(startincome-startsale-startwriteoff) as startqnt,                                --остатки стартовые 
     sum(startincome-startsale-startwriteoff+income-sale-writeoff) as endqnt    --конечные остатки
Если одно из слагаемых NULL, как думаешь что будет в результате? Просуммируй отдельно, а во внешем запросе сложи с учетом возможного NULL для каждого слагаемого, используя coalesce, или лучше isnull если такой есть в огнептице
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 24.04.2016, 21:21   #9
delphi159
Подтвердите свой е-майл
 
Регистрация: 27.01.2015
Сообщений: 28
По умолчанию

К сожалению и coalesce() не помогло:
Код:
SELECT
    G.Name,
    G.Doods_id,
    coalesce(dt2.startqnt,0) as startqnt,      
    coalesce(dt2.income,0)as income, 
    coalesce(dt2.sales,0)as sales,
    coalesce(dt2.writeoff,0)as writeoff,
    coalesce(dt2.endqnt,0) as endqnt
FROM Goods G
LEFT JOIN
(select                                                                            --dt2
     Goods_id,
     coalesce(sum(startincome),0) as startincome,                 
     coalesce(sum(startsale),0) as startsale,                 
     coalesce(sum(startwriteoff),0) as startwriteoff,    
     coalesce(sum(income),0) as income,              
     coalesce(sum(sale),0) as  sales,                
     coalesce(sum(writeoff),0) as writeoff,                                    
     coalesce(sum(startincome-startsale-startwriteoff),0) as startqnt,                                 
     coalesce(sum(startincome-startsale-startwriteoff+income-sale-writeoff),0) as endqnt    
from(                                                                       
     
   select  i.goods_id,
           sum(case when i.recdate<'01/01/2010' then coalesce(i.incomeqty,0) end) as startincome,
           0,
           0,                         
           sum(case when i.recdate between '01/01/2010'  and '01/01/2020' then coalesce(i.incomeqty,0) end) as income,
           0,
           0,
           'income' as which
    from income i
    where i.recdate <='01/01/2020'
    group by goods_id

  union all

    select
           s.goods_id,
           0,
           sum(case when s.recdate<'01/01/2010' then coalesce(s.saleqty,0) end) as startsale,
           0,
           0,
           sum(case when s.recdate between '01/01/2010' and '01/01/2020' then coalesce(s.saleqty,0) end) as sale,
           0,
           'sale'
    from sale s
    where s.recdate <= '01/01/2020'
    group by goods_id
 
 union all

    select
           w. goods_id,
           0, 
           0,
           sum(case when w.writeoffDate<'01/01/2010' then coalesce(w.writeoffQty,0) end) as startwriteoff,
           0,
           0,
           sum(case when w.writeoffDate between '01/01/2010' and '01/01/2020' then coalesce(w.writeoffQty,0) end) as writeoff,
           'writeoff'
    from writeoff w
    where w.writeofDate < '01/01/2020'
    group by goods_id) dt1
 group by Goods_id )dt2
 on G.Goods_id=dt2.Goods_id

Последний раз редактировалось delphi159; 24.04.2016 в 21:24.
delphi159 вне форума Ответить с цитированием
Старый 24.04.2016, 21:29   #10
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
sum(startincome-startsale-startwriteoff
Так нельзя. Если, например, startsale NULL, то и startincome-startsale-startwriteoff будет null. Не важно, что в других полях
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не могу создать запрос ksu04061992 Microsoft Office Access 4 03.03.2014 15:21
Не могу создать запрос!!! Abay19941308 PHP 8 13.11.2012 19:19
Не могу создать запрос yuliaNa03 Microsoft Office Access 3 22.11.2011 11:45
Программа на заказ (нужен SQL запрос, который будет объединять всех игроков в базе в один Alias) SeveNDragonS Фриланс 0 04.08.2011 04:55
Помогите создать сложный запрос (или как писать код для столбца запроса) kukuanna Microsoft Office Access 0 24.07.2009 14:10