我需要一个在日期和状态之间进行计数的存储过程。
我有一个products
表,如下所示:
ProductId(PK) ProductTypeId(FK)
-------------------------------
1 3
2 3
3 2
4 1
5 1
每次在此products
表中插入一行,即表示已售出新产品。
我在ProductTypeId
列中只有3种产品,它实际上代表一台服务器,我的客户可以取消该服务器并取消其状态或将其保持为暂停状态,这使我们可以看到状态表的历史记录像这样:
“历史记录状态表”:
StatusId(PK) ProductId(FK) StatusDate ProductStatus(FK)
1 ,1 ,1-1-17 ,1
2 ,1 ,2-12-17 ,2
3 ,2 ,21-5-17 ,1
4 ,3 ,11-5-18 ,1
5 ,2 ,18-5-18 ,2
6 ,2 ,10-8-18 ,3
我只有1,2,3种状态(“ ProductStatus”字段)三种。
“ StatusDate”字段代表状态更改的日期,因此,客户第一次购买产品/服务时,他/她将拥有一个永不改变的“ ProductTypeId”(1、2或3),并且“ ProductStatus”为1,但将来可以随时更改。
有时候,我的客户想取消(ProductStatus = 3)该产品/服务或保留为“保留”(ProductStatus = 2),并且发生这种情况时,新行将添加到“历史记录状态表”中,状态的日期已更改(“ StatusDate”字段)。
我的目标是计算每月(每月31号)处于状态1(有效)的ProductType
。
因此,如果我们有一个产品在19/1/19中处于状态1,并且状态直到19/4/19才改变,这意味着我需要在2月和3月进行计数。
存储过程的结果应类似于:
year month productId(1) productId(2) productId(3)
-------------------------------------------------------------------
2017 1 0 0 1
2017 2 0 0 1
2017 3 0 0 1
2017 4 0 0 1
2017 5 0 0 2
2017 6 0 0 2
以此类推。...
表结构:
CREATE TABLE [dbo].[tbl_SalesProducts]
(
[ProductId] [int] IDENTITY(1,1) NOT NULL,
[ProductTypeId] [tinyint] NOT NULL,
CONSTRAINT [PK_tbl_SalesProducts]
PRIMARY KEY CLUSTERED ([ProductId] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[tbl_SalesProductStatusHistory]
(
[StatusId] [int] IDENTITY(1,1) NOT NULL,
[ProductId] [int] NOT NULL,
[StatusDate] [date] NOT NULL,
[ProductStatus] [tinyint] NOT NULL,
CONSTRAINT [PK_tbl_SalesProductStatus]
PRIMARY KEY CLUSTERED ([StatusId] 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
SET IDENTITY_INSERT [dbo].[tbl_SalesProducts] ON
GO
INSERT INTO [dbo].[tbl_SalesProducts] ([ProductId], [ProductTypeId])
VALUES (1, 1), (2, 3), (3, 2), (4, 1), (5, 1)
GO
SET IDENTITY_INSERT [dbo].[tbl_SalesProducts] OFF
GO
SET IDENTITY_INSERT [dbo].[tbl_SalesProductStatusHistory] ON
GO
INSERT INTO [dbo].[tbl_SalesProductStatusHistory] ([StatusId], [ProductId], [StatusDate], [ProductStatus])
VALUES (1, 1, CAST(N'2017-12-23' AS Date), 1),
(2, 2, CAST(N'2018-01-02' AS Date), 1),
(4, 1, CAST(N'2018-02-18' AS Date), 2),
(5, 3, CAST(N'2018-03-19' AS Date), 1),
(6, 4, CAST(N'2018-04-24' AS Date), 1),
(7, 2, CAST(N'2018-04-07' AS Date), 3),
(8, 5, CAST(N'2018-07-09' AS Date), 1)
GO
SET IDENTITY_INSERT [dbo].[tbl_SalesProductStatusHistory] OFF
GO
ALTER TABLE [dbo].[tbl_SalesProducts] WITH CHECK
ADD CONSTRAINT [FK_tbl_SalesProducts_tbl_Products]
FOREIGN KEY([ProductTypeId]) REFERENCES [dbo].[tbl_Products] ([MezaeeMuzar])
GO
ALTER TABLE [dbo].[tbl_SalesProducts] CHECK CONSTRAINT [FK_tbl_SalesProducts_tbl_Products]
GO
ALTER TABLE [dbo].[tbl_SalesProductStatusHistory] WITH CHECK
ADD CONSTRAINT [FK_tbl_SalesProductStatus_tbl_SalesProducts]
FOREIGN KEY([ProductId]) REFERENCES [dbo].[tbl_SalesProducts] ([ProductId])
GO
ALTER TABLE [dbo].[tbl_SalesProductStatusHistory] CHECK CONSTRAINT [FK_tbl_SalesProductStatus_tbl_SalesProducts]
GO
ALTER TABLE [dbo].[tbl_SalesProductStatusHistory] WITH CHECK
ADD CONSTRAINT [FK_tbl_SalesProductStatusHistory_tbl_SalesProductsStatus]
FOREIGN KEY([ProductStatus]) REFERENCES [dbo].[tbl_SalesProductStatus] ([MezaeeStatusMuzar])
GO
ALTER TABLE [dbo].[tbl_SalesProductStatusHistory] CHECK CONSTRAINT [FK_tbl_SalesProductStatusHistory_tbl_SalesProductsStatus]
GO