基于库存和事务的SQL余额计算

基于库存和事务的SQL余额计算,sql,sql-server,Sql,Sql Server,我正在创建一个计算用户库存状态的存储过程 想象一下,下表名为user\u inventory,其中有许多编号列: id_inventory id_user 0 1 2 3 ------------ ------- - - - - 2 4 5 0 14 21 另一个名为user\u transactions id_tran id_user 0 1 2

我正在创建一个计算用户库存状态的存储过程

想象一下,下表名为
user\u inventory
,其中有许多编号列:

id_inventory    id_user    0    1    2    3
------------    -------    -    -    -    -
           2          4    5    0    14   21
另一个名为
user\u transactions

id_tran    id_user   0    1    2    3
-------    -------   -    -    -    -
     54          4   1    0    3    7
     55          4   2    0    9    8
     56          4   1    0    2    4
我想要的是一种在减去所有用户事务的总和后计算每列剩余库存状态的方法,如下所示:

id_availableInventory    id_user    0    1    2    3
---------------------    -------    -    -    -    -
                    2          4    1    0    0    2
另一个障碍是有标记为0到499的列

我曾尝试使用while循环,并使用动态sql和SUM()一次更新一列,但同时存在范围和性能问题——我不确定这是否是解决此问题的好方法。我正在使用SQL Server 2012

DECLARE @counter int  
DECLARE @userid int
DECLARE @amount int
DECLARE @sum int
declare @sql nvarchar(1000)
SET @counter = 0  
SET @userid = 4 
WHILE @counter < 500  
BEGIN   
    set @sql = 'SELECT @amount = [' + CAST(@counter AS nvarchar) + '] FROM user_inventory WHERE ID_User = ' +CAST(@userid AS nvarchar)
    EXEC(@sql)
    set @sql = 'SELECT @sum = SUM([' + CAST(@counter AS nvarchar) + ']) FROM user_transactions WHERE ID_User = ' +CAST(@userid AS nvarchar)
    EXEC(@sql)
    set @sql = 'UPDATE user_availableinventory SET [' + CAST(@counter AS nvarchar) + '] = @amount - @sum WHERE ID_User = ' +CAST(@userid AS nvarchar)
    EXEC(@sql)
    SET @counter = @counter + 1  
END  
DECLARE@counter int
声明@userid int
声明@amount int
声明@sum int
声明@sql nvarchar(1000)
设置@counter=0
设置@userid=4
而@counter<500
开始
设置@sql='从用户资源清册中选择@amount=['+CAST(@counter AS nvarchar)+'],其中ID_user='+CAST(@userid AS nvarchar)
EXEC(@sql)
set@sql='从用户事务中选择@sum=sum(['+CAST(@counter AS nvarchar)+']),其中ID\u user='+CAST(@userid AS nvarchar)
EXEC(@sql)
set@sql='updateuser\u availableinventory set['+CAST(@counter AS nvarchar)+']=@amount-@sum,其中ID\u user='+CAST(@userid AS nvarchar)
EXEC(@sql)
设置@counter=@counter+1
结束
返回的
必须多次声明标量变量“@amount”。

我知道这是一个丑陋的方法,对此问题的任何建议都非常感谢。

您得到了错误,因为您使用的变量超出了变量的范围。查询字符串作为单独的会话执行,因此需要声明查询字符串中的变量

您可以通过在查询字符串中声明变量来尝试这一点

DECLARE @counter int  
DECLARE @userid int
declare @sql nvarchar(1000)
SET @counter = 0  
SET @userid = 4 
WHILE @counter < 500  
BEGIN   
    set @sql = '
    DECLARE @sum int  
    DECLARE @amount int

    SELECT 
        @amount = [' + CAST(@counter AS nvarchar) + '] 
        FROM user_inventory WHERE ID_User = ' +CAST(@userid AS nvarchar)+'

    SELECT 
        @sum = SUM([' + CAST(@counter AS nvarchar) + ']) 
        FROM user_transactions WHERE ID_User = ' +CAST(@userid AS nvarchar)+'

    UPDATE user_availableinventory SET [' + CAST(@counter AS nvarchar) + '] = @amount - @sum WHERE ID_User = ' +CAST(@userid AS nvarchar)

    EXEC(@sql)
    SET @counter = @counter + 1  

END  
DECLARE@counter int
声明@userid int
声明@sql nvarchar(1000)
设置@counter=0
设置@userid=4
而@counter<500
开始
set@sql='1!'
声明@sum int
声明@amount int
挑选
@金额=['+CAST(@counter AS nvarchar)+']
来自用户资源清册,其中ID_user='+CAST(@userid AS nvarchar)+'
挑选
@sum=sum(['+CAST(@counter作为nvarchar)+']))
来自用户事务,其中ID_user='+CAST(@userid AS nvarchar)+'
更新用户可用库存集['+CAST(@counter作为nvarchar)+']=@amount-@sum其中ID\u user='+CAST(@userid作为nvarchar)
EXEC(@sql)
设置@counter=@counter+1
结束

想象一张有许多数字列的表对我来说简直是一场噩梦。您应该修复数据结构。任何进入这些列的内容都应该在单独的行中。因此,与此结构不同,一个每个用户帐户有500行,列为“id,inventoryID,amount”的结构更快更好?这与关系数据库的合理数据结构并不相似。第0、1、2、3列????不知道你为什么要这样做。这应该是一个update语句。您迫切需要修复这个数据结构或考虑使用NoSQL类型的存储。这修正了错误,但没有解决这一灾难的可怕设计。你仍然应该得到+1,但是哇……我为OP感到难过,他们将不得不处理这个问题。当你已经有了表中的数据时,讨论设计问题已经太迟了。这实现了我开始做的事情,但过程非常缓慢(13秒)。我需要改变我的整个结构。幸运的是,这个结构还在设计中,我有时间在它投入生产之前对它进行返工。我完全不同意这一点。仅仅因为数据在表中并不意味着你被设计卡住了,修复它就更复杂了。改变结构肯定会提高性能