On the Firebird 2.5 server in the database there are tables: goods, income, sale.
Goods: goods_id, name Income: Income_id, Goods_id, incomeqty (quantity), recdate Sale: sales_id,income_id,Goods_id,saleqty,recdate There is a query that selects incomes, expenses, and balances (difference) in the time interval:
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 But I want to add starting balances in it.
starting balances up to the time interval = sum (exits) to the time interval-sum (expenses) to the time interval.
The end balances at the end of the time interval = starting balances + exits in the interval-costs in the interval. starting balance in my opinion should get this:
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, 'sale' from sale where sale.recdate < :d1 group by goods_id group by goods_id Where and how to include in the main request a request for getting starting balances?
UPDATE 1:
rewrote the request, but for some reason the final residues incorrectly receive (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, 0, --списывание товара sum(case when i.recdate between '01/01/2010' and '01/01/2020' then i.incomeqty 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 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 and the final query give the following result: 
UPDATE 2
The reason was NULL. Everywhere you need to turn NULL into 0:
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(coalesce(startincome,0)-coalesce(startsale,0)-coalesce(startwriteoff,0) as startqnt, --остатки стартовые sum(coalesce(startincome,0)-coalesce(startsale,0)-coalesce(startwriteoff,0)+coalesce(income,0)-coalesce(sale,0)-coalesce(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