如何计算交易中的期初和期末余额

问题描述

我需要计算期初和期末余额交易。我有三个表 OB、购买和使用。所有表的唯一 Key 是 Product id。我需要一个存储过程来获取打击结果。根据选择的产品编号需要计算期初和期末余额。

表格结构:下面的代码包含表格和示例数据

USE [BMC]
GO
/****** Object:  Table [dbo].[TBLProductOB]    Script Date: 08-07-2021 01:20:11 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TBLProductOB](
    [Skey] [int] IDENTITY(1,1) NOT NULL,[EntryDate] [date] NULL,[Productid] [int] NULL,[ProductOB] [decimal](12,3) NULL,CONSTRAINT [PK_TBLProductOB] PRIMARY KEY CLUSTERED 
(
    [Skey] ASC
)WITH (PAD_INDEX = OFF,STATISTICS_norECOmpuTE = OFF,IGnorE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[TBLProductPurchase]    Script Date: 08-07-2021 01:20:11 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TBLProductPurchase](
    [Skey] [int] IDENTITY(1,[Entrydate] [date] NULL,[P_Purchase] [decimal](12,CONSTRAINT [PK_TBLProductPurchase] PRIMARY KEY CLUSTERED 
(
    [Skey] ASC
)WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object:  Table [dbo].[TBLProductUsage]    Script Date: 08-07-2021 01:20:11 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TBLProductUsage](
    [Skey] [int] IDENTITY(1,[P_Usage] [decimal](12,CONSTRAINT [PK_TBLProductUsage] PRIMARY KEY CLUSTERED 
(
    [Skey] ASC
)WITH (PAD_INDEX = OFF,ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET IDENTITY_INSERT [dbo].[TBLProductOB] ON 

INSERT [dbo].[TBLProductOB] ([Skey],[EntryDate],[Productid],[ProductOB]) VALUES (4,CAST(N'2021-04-01' AS Date),3,CAST(100.000 AS Decimal(12,3)))
INSERT [dbo].[TBLProductOB] ([Skey],[ProductOB]) VALUES (6,1,CAST(10.000 AS Decimal(12,[ProductOB]) VALUES (7,2,CAST(150.000 AS Decimal(12,3)))
SET IDENTITY_INSERT [dbo].[TBLProductOB] OFF
SET IDENTITY_INSERT [dbo].[TBLProductPurchase] ON 

INSERT [dbo].[TBLProductPurchase] ([Skey],[Entrydate],[P_Purchase]) VALUES (1,CAST(N'2021-07-06' AS Date),3)))
INSERT [dbo].[TBLProductPurchase] ([Skey],[P_Purchase]) VALUES (7,CAST(N'2021-07-01' AS Date),CAST(50.000 AS Decimal(12,[P_Purchase]) VALUES (8,CAST(N'2021-07-15' AS Date),[P_Purchase]) VALUES (9,CAST(1.000 AS Decimal(12,[P_Purchase]) VALUES (10,CAST(N'2021-07-03' AS Date),[P_Purchase]) VALUES (11,CAST(N'2021-07-05' AS Date),CAST(3.000 AS Decimal(12,[P_Purchase]) VALUES (12,[P_Purchase]) VALUES (13,CAST(N'2021-07-02' AS Date),[P_Purchase]) VALUES (14,[P_Purchase]) VALUES (15,5,3)))
SET IDENTITY_INSERT [dbo].[TBLProductPurchase] OFF
SET IDENTITY_INSERT [dbo].[TBLProductUsage] ON 

INSERT [dbo].[TBLProductUsage] ([Skey],[P_Usage]) VALUES (7,3)))
INSERT [dbo].[TBLProductUsage] ([Skey],[P_Usage]) VALUES (8,[P_Usage]) VALUES (9,CAST(N'2021-07-08' AS Date),[P_Usage]) VALUES (10,CAST(30.000 AS Decimal(12,[P_Usage]) VALUES (11,CAST(2.000 AS Decimal(12,[P_Usage]) VALUES (12,[P_Usage]) VALUES (13,[P_Usage]) VALUES (14,[P_Usage]) VALUES (16,[P_Usage]) VALUES (17,[P_Usage]) VALUES (18,CAST(N'2021-07-04' AS Date),3)))
SET IDENTITY_INSERT [dbo].[TBLProductUsage] OFF

刚试过:我不知道如何编写基于事务的存储过程。我只是在 union 的帮助下获得了所有表格结果。

Declare @1stopeningBalance decimal(12,3)= (select ProductOB from TBLProductOB where Productid=2)

Select a.Entrydate,a.Productid,Lag(((Sum(a.Ob)+sum(a.Purchase))-sum(a.Usage)),@1stopeningBalance) over (order by Entrydate asc) as Ob,sum(a.Purchase) as Purchase,(Sum(a.Ob)+sum(a.Purchase)) as Total,Sum(a.Usage) as Usage,((Sum(a.Ob)+sum(a.Purchase))-sum(a.Usage)) as Cb  from
(
select Entrydate,Productid,0 as Ob,Sum(Isnull(P_Purchase,0.000)) as Purchase,0 as Usage from TBLProductPurchase
group by EntryDate,Productid
union all
select Entrydate,0 as Purchase,Sum(Isnull(P_Usage,0.000)) as Usage from TBLProductUsage
group by EntryDate,Productid
) as a
where Entrydate between '2021-07-01' and '2021-07-05' and Productid=2 
group by a.EntryDate,a.Productid

Above Query Output

所需的输出结果:

Required Output

解决方法

您可以使用 LEADLAG 函数来执行此操作

确保您只有一个输入日期记录。如果您在同一日期有多个条目,则必须使用唯一键来订购

假设:可以计算期末余额,只需要计算期初余额,需要系统开始期初余额

Create table #temp_TBL(EntryDate date,Purchase decimal(18,2),total decimal(18,Usage decimal(18,CB decimal(18,2))


Declare @1stOpeningBalance decimal(18,2)=150

    Insert into #temp_TBL (EntryDate,Purchase,total,Usage,CB)
    values
    ('2021-07-01',10,160,2,158),('2021-07-02',168,166),('2021-07-03',166,164),('2021-07-04',164,162),('2021-07-05',172,170)
    
    select EntryDate,Lag(CB,1,@1stOpeningBalance) over (order by EntryDate ASC) as OB,CB from #temp_TBL

输出

enter image description here