每个月末使用FIFO概念的SQL for Balance Inventory

时间:2015-01-17 12:13:18

标签: sql

对于这些数据,我想编写一个程序,在每个月末给出余额清单。换句话说,我们可以说我必须在每月末(不是逐月)找到FIFO概念的运行平衡。这是表

create Table transactions ( [Date] Date, SECURITY_NAME VarChar(20), LOC VarChar(20), Investor VarChar(20), BUY_SELL VarChar(10), Quantity numeric(11, 2), TRANS_RATE numeric(11, 2), Inventory_value numeric(11,2) )

Insert into transactions values ('1-Jan-2014', 'HDFC', 'HO', 'OS', 'B', 125.00, 125.00, null) 
Insert into transactions values ('2-Jan-2014', 'ICICI', 'HO', 'OS', 'B', 150.00, 145.00, null) 
Insert into transactions values ('3-Jan-2014', 'Axis', 'HO', 'OS', 'B', 25.00, 150.00, null) 
Insert into transactions values ('4-Feb-2014', 'ICICI', 'HO', 'OS', 'B', 100.00, 150.00, null) 
Insert into transactions values ('5-Feb-2014', 'ICICI', 'HO', 'OS', 'S', 50.00, 185.00, null) 
Insert into transactions values ('6-Feb-2014', 'HDFC', 'HO', 'OS', 'S', 50.00, 125.00, null) 
Insert into transactions values ('1-Mar-2014', 'HDFC', 'HO', 'OS', 'B', 100.00, 125.00, null) 
Insert into transactions values ('2-Mar-2014', 'ICICI', 'HO', 'OS', 'S', 125.00, 145.00, null) 
Insert into transactions values ('3-Mar-2014', 'HDFC', 'HO', 'OS', 'S', 125.00, 150.00, null) 
Insert into transactions values ('4-Mar-2014', 'ICICI', 'HO', 'OS', 'B', 100.00, 175.00, null) 
Insert into transactions values ('6-Mar-2014', 'Axis', 'HO', 'OS', 'B', 125.00, 125.00, null) 
Insert into transactions values ('5-Apr-2014', 'Axis', 'HO', 'OS', 'S', 75.00, 185.00, null) 
Insert into transactions values ('6-Apr-2014', 'ICICI', 'HO', 'OS', 'S', 50.00, 125.00, null) 
Insert into transactions values ('6-Apr-2014', 'HDFC', 'HO', 'OS', 'B', 25.00, 125.00, null) 
update transactions set Inventory_value=(quantity*trans_rate)

我试图得到这样的输出,即每个月末的数量余额(仅限FIFO)

Month   SECURITY_NAME   LOC     Investor    Balance_Qty     Inventry_value 
Jan     HDFC            HO      OS          125             15625 
Jan     ICICI           HO      OS          150             21750 
Jan     Axis            HO      OS          25              3750 
Feb     ICICI           HO      OS          200             29500 
Feb     HDFC            HO      OS          75              9375 
Feb     Axis            HO      OS          25              3750 
Mar     HDFC            HO      OS          50              7500 
Mar     ICICI           HO      OS          175             23750 
Mar     Axis            HO      OS          150             19375 
Apr     Axis            HO      OS          75              9375 
Apr     ICICI           HO      OS          125             21250 
Apr     HDFC            HO      OS          75              10625

Inventory_value=(quantity*trans_rate)

1 个答案:

答案 0 :(得分:0)

我在查询中写了逻辑

CREATE TABLE #NEWTABLE([Month] VARCHAR(20),   SECURITY_NAME VARCHAR(50),   LOC VARCHAR(50),     Investor VARCHAR(50),    Balance_Qty INT,     Inventry_value NUMERIC(18,2))

DECLARE @RNO INT
DECLARE @DATE DATE
DECLARE @SECURITYNAME VARCHAR(50)
DECLARE @LOC VARCHAR(50)
DECLARE @INVESTOR VARCHAR(50)
DECLARE @BUYSELL CHAR
DECLARE @QUANTITY INT
DECLARE @PREV_MONTH_QUANTITY INT
DECLARE @SELL_QUANTITY INT

DECLARE @BAL_QUANTITY INT
DECLARE @RNO_MONTHDATES INT
DECLARE @LASTINMONTH INT

DECLARE @FIRSTMONTH DATE
DECLARE @PREV_MONTH DATE

SELECT @FIRSTMONTH = MIN([DATE]) FROM transactions


DECLARE rollCursor CURSOR FOR 
SELECT *,
MAX(RNO_MONTHDATES) OVER(PARTITION BY DATEPART(MONTH,[DATE]))MAXX 
FROM
(
    select [DATE],SECURITY_NAME,LOC,INVESTOR,BUY_SELL,QUANTITY,
    ROW_NUMBER() OVER(PARTITION BY DATEPART(MONTH,[DATE]),SECURITY_NAME ORDER BY DATEPART(MONTH,[DATE]), SECURITY_NAME,BUY_SELL) RNO 
    ,ROW_NUMBER() OVER(PARTITION BY DATEPART(MONTH,[DATE]) ORDER BY DATEPART(MONTH,[DATE]), (SELECT(0))) RNO_MONTHDATES
    from transactions
)TAB
ORDER BY DATEPART(MONTH,[DATE]), SECURITY_NAME,BUY_SELL,RNO_MONTHDATES

OPEN rollCursor

-- Loop starts from here 
FETCH NEXT FROM rollCursor
INTO @DATE,@SECURITYNAME,@LOC,@INVESTOR,@BUYSELL,@QUANTITY,@RNO,@RNO_MONTHDATES,@LASTINMONTH

WHILE @@FETCH_STATUS = 0
BEGIN

     -- First month's records will be inserted directly
     IF(DATEPART(MONTH,@DATE) = DATEPART(MONTH,@FIRSTMONTH))
     BEGIN
            INSERT INTO #NEWTABLE
            SELECT @DATE,@SECURITYNAME,@LOC,@INVESTOR,@QUANTITY,NULL
     END

     ELSE IF(DATEPART(MONTH,@DATE) <> DATEPART(MONTH,@FIRSTMONTH))
     BEGIN

        -- If Buy is the 1st record for a SECURITYNAME then it will not take SELL because its  already included inside the below the query
        IF(@RNO = 1)
        BEGIN

            IF(@BUYSELL = 'S')
            BEGIN
                SET @QUANTITY = 0
            END

            SET @PREV_MONTH_QUANTITY=0
            SET @SELL_QUANTITY=0

            -- Finds previous month quantity
            SELECT  @PREV_MONTH_QUANTITY = ISNULL(Balance_Qty,0)
            FROM #NEWTABLE 
            WHERE SECURITY_NAME = @SECURITYNAME
            AND DATEPART(MONTH,[MONTH]) = 
            (SELECT MAX(DATEPART(MONTH,[MONTH])) FROM #NEWTABLE WHERE DATEPART(MONTH,[MONTH]) < DATEPART(MONTH,CAST(@DATE AS DATE)))

            -- Find current month's Sell Quantity of current SECURITYNAME 
            SELECT @SELL_QUANTITY  = ISNULL(Quantity,0) FROM transactions 
            WHERE SECURITY_NAME = @SECURITYNAME AND BUY_SELL = 'S' AND DATEPART(MONTH,@DATE) = DATEPART(MONTH,[DATE])

            INSERT INTO #NEWTABLE
            SELECT @DATE,@SECURITYNAME,@LOC,@INVESTOR,(@PREV_MONTH_QUANTITY+@QUANTITY)-@SELL_QUANTITY,NULL

        END     

        -- If it is last record in current month, it finds out the missing SECURITYNAME in current month, take from previous month and add as current month
        IF(@RNO_MONTHDATES = @LASTINMONTH)
        BEGIN

            INSERT INTO #NEWTABLE
            SELECT CAST(CAST(YEAR([MONTH]) AS VARCHAR(4))+'-'+CAST(MONTH(@DATE) AS VARCHAR(14))+'-01' AS DATE),
            SECURITY_NAME,LOC,INVESTOR,BALANCE_QTY,INVENTRY_VALUE 
            FROM #NEWTABLE
            WHERE SECURITY_NAME IN
            (
                SELECT SECURITY_NAME 
                FROM #NEWTABLE 
                WHERE DATEPART(MONTH,[MONTH]) = 
                (SELECT MAX(DATEPART(MONTH,[MONTH])) FROM #NEWTABLE WHERE DATEPART(MONTH,[MONTH]) < DATEPART(MONTH,@DATE))         
                EXCEPT
                SELECT SECURITY_NAME 
                FROM #NEWTABLE 
                WHERE DATEPART(MONTH,[MONTH]) = DATEPART(MONTH,@DATE)
            )
            AND DATEPART(MONTH,[MONTH]) = 
            (SELECT MAX(DATEPART(MONTH,[MONTH])) FROM #NEWTABLE WHERE DATEPART(MONTH,[MONTH]) < DATEPART(MONTH,@DATE))         

        END

     END

    FETCH NEXT FROM rollCursor
    INTO @DATE,@SECURITYNAME,@LOC,@INVESTOR,@BUYSELL,@QUANTITY,@RNO,@RNO_MONTHDATES,@LASTINMONTH
END 

CLOSE rollCursor;
DEALLOCATE rollCursor;


SELECT CAST(DATENAME(MONTH,[Month])AS VARCHAR(3)), SECURITY_NAME,LOC,Investor,Balance_Qty,Inventry_value  
FROM #NEWTABLE

请添加计算以查找新表的Inventry_value