使用上一行中同一列的值更新SQL表中的列

时间:2019-02-21 15:09:22

标签: sql sql-server tsql

我有一个具有以下布局和值的表

Table Initial Layout 我希望根据以下规则更新“ PrevMonthly Amount”列的数据

对于REFNO和KEY的组合,

  • 如果一笔交易是第一笔交易,则PrevMonthly Amount = 0
  • 如果某笔交易是新月(即)该月的第一笔交易 是DATE的更改,则PrevMonthly Amount = Prev Amount
  • 否则,PrevMonthly金额=上一个的PrevMonthly金额 REFNO和KEY相同组合的交易

最终预期结果将是

Table Result

我尝试在SQL中使用LAG函数,但没有得到如上所示的预期结果。

SELECT REFNO, KEY, SEQNO,  
LAG(DATE,1) OVER (PARTITION BY REFNO, KEY ORDER BY REFNO, KEY, SEQNO) as DATE_Prev  
INTO #TEMP_TABLE  
FROM MainTable  

UPDATE A SET  
A.PrevMonthlyAmount = CASE WHEN A.DATE <> B.DATE_Prev  
THEN A.PrevAmount ELSE A.PrevMonthlyAmount END              

FROM MainTable A  
JOIN #Temp_Table B  
ON A.REFNO = B.REFNO And A.KEY = B.KEY And A.SEQNO = B.SEQNO

UPDATE A SET  
A.PrevMonthlyAmount = CASE WHEN A.DATE = B.DATE_PREV  
THEN (SELECT PrevMonthlyAmount From STAGE_LARGE_BANDED Where SEQNO = A.SEQNO - 1 And REFNO = A.REFNO And KEY = A.KEY AND)  
ELSE A.PrevMonthlyAmount END                         

FROM MainTable A  
JOIN #Temp_Table B  
ON A.REFNO = B.REFNO And A.KEY = B.KEY And A.SEQNO =  B.SEQNO  

我在表布局中指示的数据集只是一个示例,并且正在处理的表中,在实时情况下,该表将具有近几百万行。

查询得到的结果如下

enter image description here

创建表和插入查询如下,

    CREATE TABLE [dbo].[MAINTABLE](
        [REFNO] [int] NULL,
        [KEY]   [Int] NULL, 
        [SEQNO] [int] NULL, 
        [DATE]  [int] NULL, 
        [AMOUNT] [int] NULL,
        [PrevAMOUNT] [int] NULL,
        [PrevMonthlyAmount] [int] NULL,
     ) 

     INSERT INTO MAINTABLE Values(1000000,2,1,201801,100,0,0)
     INSERT INTO MAINTABLE Values(1000000,2,2,201801,200,100,0)
     INSERT INTO MAINTABLE Values(1000000,2,3,201802,300,200,0)
     INSERT INTO MAINTABLE Values(1000000,2,4,201802,400,300,0)
     INSERT INTO MAINTABLE Values(1000000,2,5,201802,420,400,0)
     INSERT INTO MAINTABLE Values(1000000,2,6,201803,450,400,0)

     INSERT INTO MAINTABLE Values(2000000,1,1,201801,150,0,0)
     INSERT INTO MAINTABLE Values(2000000,1,2,201801,250,150,0)
     INSERT INTO MAINTABLE Values(2000000,1,3,201801,350,250,0)

     INSERT INTO MAINTABLE Values(3000000,1,1,201801,175,0,0)
     INSERT INTO MAINTABLE Values(3000000,1,2,201802,275,175,0)
     INSERT INTO MAINTABLE Values(3000000,1,3,201803,375,275,0)

3 个答案:

答案 0 :(得分:2)

您可以apply

select t.*, t1.prevmonthly_amount
from table t outer apply
    (select top (1) t1.amount as prevmonthly_amount
     from table t1
     where t.refno = t1.refno and t.key = t1.key and
           t1.date < t.date
     order by  t1.seqno desc
    ) t1;

答案 1 :(得分:1)

嗯。 。 。前一个月的金额似乎是该月的第一个值。因此,我认为这适用于您的数据:

select t.*,
       first_value(prevamount) over (partition by refno, key, date order by seqno) as prevmonthly_amount
from t;

Here是db <>小提琴。

答案 2 :(得分:0)

非常感谢您的所有时间和投入。

我尝试了一些解决问题的方法,并找到了解决方案!!!

但是我绝对相信,总有比这更好的解决方案...:):)

请参见下文

CREATE TABLE [dbo].[MAINTABLE](
    [REFNO] [int] NULL,
    [KEY] [int] NULL,
    [SEQNO] [int] NULL,
    [DATE] [int] NULL,
    [AMOUNT] [int] NULL,
    [PrevAMOUNT] [int] NULL,
    [PrevMonthlyAmount] [int] NULL
) ON [PRIMARY]


 Truncate Table MAINTABLE

 INSERT INTO MAINTABLE Values(1000000,2,1,201801,100,0,0)
 INSERT INTO MAINTABLE Values(1000000,2,2,201801,200,100,0)
 INSERT INTO MAINTABLE Values(1000000,2,3,201802,300,200,0)
 INSERT INTO MAINTABLE Values(1000000,2,4,201802,400,300,0)
 INSERT INTO MAINTABLE Values(1000000,2,5,201802,420,400,0)
 INSERT INTO MAINTABLE Values(1000000,2,6,201803,450,420,0)

 INSERT INTO MAINTABLE Values(2000000,1,1,201801,150,0,0)
 INSERT INTO MAINTABLE Values(2000000,1,2,201801,250,150,0)
 INSERT INTO MAINTABLE Values(2000000,1,3,201801,350,250,0)

 INSERT INTO MAINTABLE Values(3000000,1,1,201801,175,0,0)
 INSERT INTO MAINTABLE Values(3000000,1,2,201802,275,175,0)
 INSERT INTO MAINTABLE Values(3000000,1,3,201803,375,275,0)

SELECT REFNO, [KEY], SEQNO,  
LAG(DATE,1) OVER (PARTITION BY REFNO, [KEY] ORDER BY REFNO, [KEY], SEQNO) as DATE_Prev  
INTO #TEMP_TABLE  
FROM MainTable  

UPDATE A SET  
A.PrevMonthlyAmount = 
CASE WHEN A.DATE <> B.DATE_Prev  
    THEN A.PrevAmount 
    ELSE A.PrevMonthlyAmount
 END              

FROM MainTable A  
JOIN #Temp_Table B  
ON A.REFNO = B.REFNO And A.[KEY] = B.[KEY] And A.SEQNO = B.SEQNO

SELECT A.* 
INTO #TEMP_TABLE2
FROM MAINTABLE A 
JOIN (SELECT REFNO, [KEY], [DATE], MIN(SEQNO) as FirstTransId From MAINTABLE
        GROUP BY REFNO, [KEY], [DATE]) B
ON A.REFNO = B.REFNO And A.[KEY] = B.[KEY] And A.[DATE] = B.[DATE] And A.SEQNO = B.FirstTransId


UPDATE A SET  
A.PrevMonthlyAmount = B.PrevMonthlyAmount

FROM MainTable A  
JOIN #TEMP_TABLE2 B  
ON A.REFNO = B.REFNO And A.[KEY] = B.[KEY] And A.[DATE] =  B.[DATE]  
Where A.SEQNO <> B.SEQNO

Select * from MAINTABLE