我要计算业务应用程序的期初余额和期末余额。但是对于某些行,期初余额产生错误。我有以下数据表:
SupplierPayments
DateOfPayment Bill
2018-06-01 4000
2018-06-01 9000
2018-06-19 2000
2018-06-19 6000
2019-03-28 3000
2019-03-29 5000
Expensis
DateOfExpense Expense
2018-08-14 2,000
2019-02-26 8,000
2019-03-28 2000
2019-03-29 2000
收入
DateSold Income
2018-09-27 24,000
2018-10-17 8,000
2019-01-01 13,000
2019-03-28 10,000
SQL Server 2012查询
with Income( DateSold, Income ) as (
select DateSold,isnull(sum(TotalBill),0)
from SalesInvoice group by DateSold
), SupplierPayments( DateOfPayment,Bill ) as(
select DateOfPayment,isnull(sum(BillPaidAmount),0)
from SupplyInvoicePaymentHistory group by DateOfPayment
), Expensis( DateOfExpense, Expense ) as(
select Date ,isnull(sum(Amount),0)
from GeneralExpense group by Date
), t as (
select i.DateSold
,e.DateOfExpense
,sp.DateOfPayment
,i.income
, e.Expense
,sp.Bill
, sum(isnull(i.income,0)-(isnull(e.Expense,0)+isnull(sp.Bill,0))) over (order by i.DateSold,e.DateOfExpense,sp.DateOfPayment) as closing_balance
from income i
full outer join expensis e on e.DateOfExpense = i.DateSold
full outer join SupplierPayments sp on sp.DateOfPayment=e.DateOfExpense
)
select m.EventDate, m.DateSold
,m.DateOfExpense
,m.DateOfPayment
,isnull(m.opening_balance,0) as Opening_Balance
,isnull(m.Income,0) as Income
,isnull(m.Expense,0) as Expensis
,isnull(m.Bill,0) as SupplierPayments
,isnull(m.closing_balance,0) as Closing_Balance
from (
select coalesce(coalesce(DateOfPayment, DateOfExpense), DateSold) EventDate, DateSold
,DateOfExpense
,DateOfPayment
,lag(closing_balance,1,0) over (order by DateSold, DateOfExpense,DateOfPayment) as opening_balance
,Income
,Expense
,closing_balance
,Bill
from t
) as m order by m.EventDate ASC
输出
EventDate DateSold ExpenseDate PaymentDate Opening Income Expense Bill Closing
2018-06-01 NULL NULL 2018-06-01 0 0 0 13000 -13000
2018-06-19 NULL NULL 2018-06-19 -13000 0 0 8000 -21000
2018-08-14 NULL 2018-08-14 NULL -21000 0 2000 0 -23000
2018-09-27 2018-09-27 NULL NULL -30000 24000 0 0 -6000
2019-01-01 2019-01-01 NULL NULL -6000 13000 0 0 7000
2019-03-28 2019-03-28 2019-03-28 2019-03-28 7000 10000 2000 3000 12000
2019-03-29 NULL 2019-03-29 2019-03-29 -23000 0 2000 5000 -30000
计算期末余额的公式如下:
Closing = Opening + Income - Expense - Bill
我们可以注意到,日期2018-09-27
的期初余额为-30,000
,这是错误的。它应该是-23,000
。同样,日期2019-03-29
的期初结余也是错误的。
必需的结果
EventDate DateSold ExpenseDate PaymentDate Opening Income Expense Bill Closing
2018-06-01 NULL NULL 2018-06-01 0 0 0 13000 -13000
2018-06-19 NULL NULL 2018-06-19 -13000 0 0 8000 -21000
2018-08-14 NULL 2018-08-14 NULL -21000 0 2000 0 -23000
2018-09-27 2018-09-27 NULL NULL -23000 24000 0 0 1000
2019-01-01 2019-01-01 NULL NULL 1000 13000 0 0 14000
2019-03-28 2019-03-28 2019-03-28 2019-03-28 14000 10000 2000 3000 19000
2019-03-29 NULL 2019-03-29 2019-03-29 19000 0 2000 5000 12000
有可能在任何一天都没有出售任何物品,但是有费用或账单付给了供应商,反之亦然。
此外,任何表都可能在同一日期具有两个条目。
答案 0 :(得分:0)
您的问题位于SUM
和LAG
的按列排序。如果仅从CTE中进行选择,则会发现您未按三个日期(可用)中的任何日期进行排序,而是按指定的顺序对其进行排序。因此,您将在第一列中获得NULL,然后在第二列中获得NULL,等等。您需要做的是尽快在t中引入EventDate,并对其进行排序。
;with xIncome( DateSold, Income ) as (
select DateSold,isnull(sum(income),0)
from income group by DateSold
), xSupplierPayments( DateOfPayment,Bill ) as(
select DateOfPayment,isnull(sum(bill),0)
from supplierpayments group by DateOfPayment
), xExpensis( DateOfExpense, Expense ) as(
select DateOfExpense Date ,isnull(sum(expense),0)
from expensis group by Dateofexpense
), t as (
select i.DateSold
,e.DateOfExpense
,sp.DateOfPayment
,consolidated.date consolidatedDate
,i.income
, e.Expense
,sp.Bill
, sum(isnull(i.income,0)-(isnull(e.Expense,0)+isnull(sp.Bill,0))) over (order by consolidated.date) as closing_balance
from xincome i
full outer join xexpensis e on e.DateOfExpense = i.DateSold
full outer join xSupplierPayments sp on sp.DateOfPayment=e.DateOfExpense
cross apply (select coalesce(i.DateSold,e.DateOfExpense,sp.DateOfPayment) as date) consolidated
)
select consolidatedDate, m.DateSold
,m.DateOfExpense
,m.DateOfPayment
,isnull(m.opening_balance,0) as Opening_Balance
,isnull(m.Income,0) as Income
,isnull(m.Expense,0) as Expensis
,isnull(m.Bill,0) as SupplierPayments
,isnull(m.closing_balance,0) as Closing_Balance
from (
select consolidatedDate
,DateSold
,DateOfExpense
,DateOfPayment
,lag(closing_balance,1,0) over (order by consolidatedDate) as opening_balance
,Income
,Expense
,closing_balance
,Bill
from t
) as m order by m.consolidatedDate ASC
在CTE中,请注意CROSS APPLY
,其中我将所有日期COALESCE
合并为一个同名日期。我不得不重命名第一个CTE,以匹配您的示例数据表名称,但是您可以理解它的要旨。