商城积分数据库设计
2011-10-09 14:15
211 查看
需求:①积分累计:获取积分的过期时间为半年,消耗积分遵循先进先出的原则(当然要在总积分够消耗的情况下)
②积分月结:每月一号汇总上月获取和消耗积分并且扣除过期积分。
思路:主要考虑到积分结算的压力问题,若活动用户产生的数据明细成千上百万结算时就会很麻烦,考虑把一些压力转移到明细操作中:
①获取积分时同时记录在当月的月记录(稍后把数据库脚本放上)里,每月一条记录。当然会在总积分表中增加
②消耗积分时会同时在某个字段中记录当月总消耗的数量,这样就可以减少月结时的操作步骤,
③月结时要根据先进先出的原则,先从月表中扣除上月消耗的积分,然后从积分总表中扣除过期积分。
数据库简介:
辅助配置表
明细表:AppID,ModleID为辅助配置表的内容,AccountID为用户ID
月表:GetNum当月获取积分,LeaveNum当月剩余积分若过期则设置为0。
总积分表:CostNum记录消耗的积分总和,每一次结算后则重置为0;
其它:这个存储过程实现了批量更新数据,因为一个用户有多个月的积分记录,所以要使用一对多的批量更新模式,
整个数据库脚本:
模拟测试数据库脚本:
目前做到这种程度,还没具体使用不知道还有什么漏洞!
②积分月结:每月一号汇总上月获取和消耗积分并且扣除过期积分。
思路:主要考虑到积分结算的压力问题,若活动用户产生的数据明细成千上百万结算时就会很麻烦,考虑把一些压力转移到明细操作中:
①获取积分时同时记录在当月的月记录(稍后把数据库脚本放上)里,每月一条记录。当然会在总积分表中增加
②消耗积分时会同时在某个字段中记录当月总消耗的数量,这样就可以减少月结时的操作步骤,
③月结时要根据先进先出的原则,先从月表中扣除上月消耗的积分,然后从积分总表中扣除过期积分。
数据库简介:
辅助配置表
明细表:AppID,ModleID为辅助配置表的内容,AccountID为用户ID
月表:GetNum当月获取积分,LeaveNum当月剩余积分若过期则设置为0。
总积分表:CostNum记录消耗的积分总和,每一次结算后则重置为0;
其它:这个存储过程实现了批量更新数据,因为一个用户有多个月的积分记录,所以要使用一对多的批量更新模式,
ALTER PROC [dbo].[gs_MonthBalance2] AS BEGIN Declare @ExpireDate varchar(10) SET @ExpireDate=convert(char(7),DATEADD(MONTH,DATEDIFF(MONTH,0,getdate())-1,0),120)--过期积分月份(当前月的上月) ;WITH t AS( SELECT rn=ROW_NUMBER()over(Order by BalanceDate),* FROM CodeMonth), t1 AS( SELECT *,tmpsum=(SELECT SUM(LeaveNum) FROM t WHERE AccountID=a.AccountID and rn<=a.rn) FROM t a) ---批量更新数据 UPDATE a SET a.LeaveNum=a.LeaveNum-case WHEN a.LeaveNum-(a.tmpsum-b.CostNum) <=0 THEN 0 WHEN a.tmpsum-b.CostNum <=0 THEN a.LeaveNum ELSE a.LeaveNum-(a.tmpsum-b.CostNum) end FROM t1 a JOIN CodeTotle b on a.AccountID=b.AccountID WHERE b.CostNum>0--排除未消耗数量 ---清除消耗记录 UPDATE dbo.CodeTotle SET CostNum=0 WHERE CostNum>0 ---从总数中删除过期数据 UPDATE ct SET ct.CodeNum=ct.CodeNum-cm.LeaveNum FROM dbo.CodeTotle ct, (SELECT * From CodeMonth WHERE convert(char(7),[ExpireDate],120)=@ExpireDate) AS cm --(SELECT * From CodeMonth) AS cm WHERE ct.AccountID=cm.AccountID ---从月表清除过期数据 UPDATE CodeMonth SET LeaveNum=0 WHERE convert(char(7),[ExpireDate],120)=@ExpireDate --UPDATE CodeMonth SET LeaveNum=0 END
整个数据库脚本:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[CodeDetail]( [SeqID] [int] IDENTITY(1,1) NOT NULL, [AccountID] [int] NOT NULL, [AppID] [int] NOT NULL, [ModleID] [int] NOT NULL, [CodeNum] [int] NOT NULL, [Note] [varchar](200) NULL, [Des] [varchar](200) NULL, [CreateDate] [datetime] NOT NULL, [ExpireDate] [datetime] NOT NULL, [Creater] [varchar](50) NOT NULL, [CreateIP] [varchar](15) NOT NULL, CONSTRAINT [PK_CODEDETAIL] PRIMARY KEY CLUSTERED ( [SeqID] 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 ANSI_PADDING OFF GO /****** 对象: Table [dbo].[CodeConfig] 脚本日期: 10/09/2011 14:15:50 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[CodeConfig]( [SeqID] [int] IDENTITY(1,1) NOT NULL, [APPID] [int] NOT NULL, [AppName] [varchar](50) NOT NULL, [ModleID] [int] NOT NULL, [ModleName] [varchar](50) NOT NULL, [Note] [varchar](200) NULL CONSTRAINT [DF_CodeConfig_Note] DEFAULT (''), [Status] [tinyint] NOT NULL CONSTRAINT [DF_CodeConfig_Status] DEFAULT ((1)), CONSTRAINT [PK_CODECONFIG] PRIMARY KEY CLUSTERED ( [SeqID] ASC, [APPID] ASC, [ModleID] 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 ANSI_PADDING OFF GO /****** 对象: Table [dbo].[CodeAccount] 脚本日期: 10/09/2011 14:15:47 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[CodeAccount]( [UserID] [int] IDENTITY(1,1) NOT NULL, [UserName] [varchar](50) NOT NULL, [Password] [varchar](50) NOT NULL, [Status] [int] NOT NULL CONSTRAINT [DF_gs_Accounts_Status] DEFAULT ((0)), [AllowIP] [varchar](100) NOT NULL CONSTRAINT [DF_gs_Accounts_AllowIP] DEFAULT ('*'), [Created] [datetime] NOT NULL CONSTRAINT [DF__gs_Accounts_Created] DEFAULT (getdate()), [LastLogin] [datetime] NOT NULL CONSTRAINT [DF_gs_Accounts_LastLogin] DEFAULT (getdate()), [LastLoginIP] [varchar](50) NOT NULL CONSTRAINT [DF_gs_Accounts_LastLoginIP] DEFAULT ('127.0.0.1'), CONSTRAINT [PK_GS_ACCOUNTS] PRIMARY KEY CLUSTERED ( [UserName] 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 ANSI_PADDING OFF GO /****** 对象: Table [dbo].[CodeMonth] 脚本日期: 10/09/2011 14:15:54 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[CodeMonth]( [SeqID] [int] IDENTITY(1,1) NOT NULL, [AccountID] [int] NOT NULL, [GetNum] [int] NOT NULL, [CostNum] [int] NOT NULL CONSTRAINT [DF_CodeMonth_CostNum] DEFAULT ((0)), [LeaveNum] [int] NOT NULL, [BalanceDate] [datetime] NOT NULL, [ExpireDate] [datetime] NOT NULL, [Note] [varchar](200) NULL, [Exp1] [varchar](100) NULL, CONSTRAINT [PK_CODEMONTH] PRIMARY KEY CLUSTERED ( [SeqID] 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 ANSI_PADDING OFF GO /****** 对象: Table [dbo].[CodeTotle] 脚本日期: 10/09/2011 14:15:57 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[CodeTotle]( [SeqID] [int] IDENTITY(1,1) NOT NULL, [AccountID] [int] NOT NULL, [CodeNum] [int] NOT NULL, [CostNum] [int] NOT NULL CONSTRAINT [DF_CodeTotle_CostNum] DEFAULT ((0)), [Status] [tinyint] NOT NULL CONSTRAINT [DF_CodeTotle_Status] DEFAULT ((1)), [Note] [varchar](200) NULL CONSTRAINT [DF_CodeTotle_Note] DEFAULT (''), [UpdateDate] [datetime] NOT NULL, [Exp1] [varchar](100) NULL CONSTRAINT [DF_CodeTotle_Exp1] DEFAULT (''), CONSTRAINT [PK_CODETOTLE] PRIMARY KEY CLUSTERED ( [SeqID] ASC, [AccountID] 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 ANSI_PADDING OFF GO /****** 对象: StoredProcedure [dbo].[gs_CodeDetail_Add] 脚本日期: 10/09/2011 14:15:45 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER OFF GO CREATE PROCEDURE [dbo].[gs_CodeDetail_Add] @AccountID int, @AppID int, @ModleID int, @CodeNum int, @Note varchar(200), @Des varchar(200), @CreateDate datetime, @Creater varchar(50), @CreateIP varchar(15) AS Declare @ExpireDate DateTime Set @ExpireDate=DATEADD(MONTH,7+DATEDIFF(MONTH,0,@CreateDate),0)-1 --明细添加 INSERT INTO CodeDetail ([AccountID],[AppID],[ModleID],[CodeNum],[Note],[Des],[CreateDate],[ExpireDate],[Creater],[CreateIP]) VALUES (@AccountID,@AppID,@ModleID,@CodeNum,@Note,@Des,@CreateDate,@ExpireDate,@Creater,@CreateIP) --总积分 IF exists(SELECT * FROM CodeTotle WHERE AccountID= @AccountID) BEGIN UPDATE CodeTotle SET [CodeNum] = [CodeNum]+@CodeNum, [UpdateDate] = @CreateDate WHERE [AccountID] = @AccountID END ELSE BEGIN INSERT INTO CodeTotle ( [AccountID], [CodeNum], [UpdateDate] ) VALUES ( @AccountID, @CodeNum, @CreateDate ) END --月结表 --已存在当月数据(Update) IF exists(select * from dbo.CodeMonth WHERE convert(char(7),BalanceDate,120)=convert(char(7),@CreateDate,120) AND AccountID=@AccountID)--已经存在当月数据 BEGIN IF(@CodeNum>0) BEGIN UPDATE dbo.CodeMonth SET GetNum=GetNum+@CodeNum,LeaveNum=LeaveNum+@CodeNum WHERE convert(char(7),BalanceDate,120)=convert(char(7),@CreateDate,120) AND AccountID=@AccountID END ELSE BEGIN UPDATE dbo.CodeMonth SET CostNum=CostNum-@CodeNum WHERE AccountID=@AccountID AND convert(char(7),BalanceDate,120)=convert(char(7),@CreateDate,120) UPDATE dbo.CodeTotle SET CostNum=CostNum-@CodeNum WHERE AccountID=@AccountID END END --不存在当月数据(Insert) ELSE BEGIN IF(@CodeNum>0) BEGIN INSERT INTO [dbo].[CodeMonth]([AccountID],[GetNum],[CostNum],[LeaveNum],[BalanceDate],[ExpireDate]) VALUES(@AccountID,@CodeNum,0,@CodeNum,@CreateDate,@ExpireDate) END ELSE BEGIN INSERT INTO [dbo].[CodeMonth]([AccountID],[GetNum],[CostNum],[LeaveNum],[BalanceDate],[ExpireDate]) VALUES(@AccountID,0,@CodeNum,0,@CreateDate,@ExpireDate) UPDATE dbo.CodeTotle SET CostNum=CostNum-@CodeNum WHERE AccountID=@AccountID END END select SCOPE_IDENTITY() GO /****** 对象: StoredProcedure [dbo].[gs_Month_Count] 脚本日期: 10/09/2011 14:15:45 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROC [dbo].[gs_Month_Count] AS BEGIN --先把上月获得数量放入数据库 INSERT INTO CodeMonth(AccountID,GetNum,LeaveNum,BalanceDate,[ExpireDate]) SELECT AccountID, SUM(CodeNum) as GetNum,SUM(CodeNum) as LeaveNum,getdate() as BalanceDate, CONVERT(char(10),[ExpireDate],120) as [ExpireDate] FROM CodeDetail WHERE CodeNum>0 AND DATEDIFF(month,CreateDate,getdate())=1--当前结算月的上月 GROUP BY AccountID, CONVERT(char(10),[ExpireDate],120) --convert(char(7),CreateDate,120)=convert(char(7),DATEADD(MONTH,DATEDIFF(MONTH,0,getdate())-1,0),120) --计算上月消耗数量和未消耗的人 INSERT INTO dbo.CodeMonth_Temp(AccountID,ExpendCode) SELECT AccountID, -sum(CodeNum) as ExpendCode FROM CodeDetail WHERE CodeNum<0 AND datediff(month,CreateDate,getdate())=1 GROUP BY AccountID Union SELECT distinct AccountID ,0 as ExpendCode FROM CodeDetail where AccountID not in(SELECT distinct AccountID FROM CodeDetail WHERE CodeNum<0 AND datediff(month,CreateDate,getdate())=1 ) END GO /****** 对象: StoredProcedure [dbo].[gs_CodeConfig_Edit] 脚本日期: 10/09/2011 14:15:44 ******/ SET ANSI_NULLS OFF GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE [dbo].[gs_CodeConfig_Edit] @SeqID int, @APPID int, @AppName varchar(50), @ModleID int, @ModleName varchar(50), @Note varchar(200), @Status tinyint AS -- THIS STORED PROCEDURE NEEDS TO BE MANUALLY COMPLETED -- MULITPLE PRIMARY KEY MEMBERS OR NON-GUID/INT PRIMARY KEY DECLARE @Return int SET @Return =1 IF(@SeqID=0) BEGIN IF exists(SELECT * FROM CodeConfig WHERE APPID= @APPID AND ModleID=@ModleID) BEGIN Set @Return=-1 END ELSE BEGIN INSERT INTO CodeConfig ( [APPID], [AppName], [ModleID], [ModleName], [Note], [Status] ) VALUES ( @APPID, @AppName, @ModleID, @ModleName, @Note, @Status ) END END ELSE BEGIN UPDATE CodeConfig SET [AppName] = @AppName, [ModleName] = @ModleName, [Note] = @Note, [Status] = @Status WHERE [SeqID] = @SeqID AND [APPID] = @APPID AND [ModleID] = @ModleID END Select @Return as [Return] GO /****** 对象: StoredProcedure [dbo].[gs_MonthBalance2] 脚本日期: 10/09/2011 14:15:45 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROC [dbo].[gs_MonthBalance2] AS BEGIN Declare @ExpireDate varchar(10) SET @ExpireDate=convert(char(7),DATEADD(MONTH,DATEDIFF(MONTH,0,getdate())-1,0),120)--过期积分月份(当当前月的上月) ;WITH t AS( SELECT rn=ROW_NUMBER()over(Order by BalanceDate),* FROM CodeMonth), t1 AS( SELECT *,tmpsum=(SELECT SUM(LeaveNum) FROM t WHERE AccountID=a.AccountID and rn<=a.rn) FROM t a) ---批量更新数据 UPDATE a SET a.LeaveNum=a.LeaveNum-case WHEN a.LeaveNum-(a.tmpsum-b.CostNum) <=0 THEN 0 WHEN a.tmpsum-b.CostNum <=0 THEN a.LeaveNum ELSE a.LeaveNum-(a.tmpsum-b.CostNum) end FROM t1 a JOIN CodeTotle b on a.AccountID=b.AccountID WHERE b.CostNum>0--排除未消耗数量 ---清除消耗记录 UPDATE dbo.CodeTotle SET CostNum=0 WHERE CostNum>0 ---从总数中删除过期数据 UPDATE ct SET ct.CodeNum=ct.CodeNum-cm.LeaveNum FROM dbo.CodeTotle ct, (SELECT * From CodeMonth WHERE convert(char(7),[ExpireDate],120)=@ExpireDate) AS cm --(SELECT * From CodeMonth) AS cm WHERE ct.AccountID=cm.AccountID ---从月表清除过期数据 UPDATE CodeMonth SET LeaveNum=0 WHERE convert(char(7),[ExpireDate],120)=@ExpireDate --UPDATE CodeMonth SET LeaveNum=0 END GO
模拟测试数据库脚本:
DECLARE @MyCounter INT declare @the_date datetime declare @AID INT SET @AID=1000144 SET @MyCounter = 0 SET @the_date ='2011-08-01' WHILE (@MyCounter < 2000) BEGIN WAITFOR DELAY '000:00:00' EXECUTE [CodeDBV1_2].[dbo].[gs_CodeDetail_Add] @AccountID=@AID ,@AppID=1 ,@ModleID=11 ,@CodeNum=-150 ,@Note='Test' ,@Des='Test' ,@CreateDate=@the_date ,@Creater='System' ,@CreateIP='127.0.0.1' SET @AID=@AID+1 --SET @the_date =dateadd(d,1,@the_date) SET @MyCounter = @MyCounter + 1 END
目前做到这种程度,还没具体使用不知道还有什么漏洞!
相关文章推荐
- 中小型商城系统中的分类/产品属性/扩展属性的数据库设计
- 商城数据库设计原则(二)-商品模型的设计
- SSH网上商城1_数据库设计
- 夺命雷公狗ThinkPHP项目之----商城2数据库设计
- Online Shopping网上商城数据库设计
- javaWeb购物商城设计---数据库连接
- 03(maven+SSH)网上商城项目实战之数据库设计(PMD)
- 积分入学数据库设计问题汇总
- 中小型商城系统中的分类/产品属性/扩展属性的数据库设计
- 中小型商城系统中的分类/产品属性/扩展属性的数据库设计
- 在java商城开发中关系型数据库设计是是建立在关系模型基础上的数据库
- web开发之商城订单模块数据库设计
- 网上商城不同类别产品数据库的设计思路
- 商城系统商品属性的数据库设计思路
- PHP商城 商品模块 数据库 表设计
- 积分商城如何梳理思路和进行设计
- 商城 商品模块 数据库 表设计
- !金尚网上商城12-数据库设计
- (转)商城系统商品属性的数据库设计思路
- 中小型商城系统中的分类/产品属性/扩展属性的数据库设计