在SQL Server中使用ROW_NUMBER()获取上一条记录的值
希望这对于那些在SQL Server方面更有经验的人来说足够容易 我有一个客户贷款活动数据表,每当他们的帐户发生操作时,该表都会更新。例如,如果他们的限额增加,将使用他们的新限额创建一个新记录。我希望能够创建一个他们的活动列表,其中活动量是他们的新限额减去他们以前的限额 目前我有以下内容,但我正在努力找出如何访问以前的记录在SQL Server中使用ROW_NUMBER()获取上一条记录的值,sql,sql-server,row-number,Sql,Sql Server,Row Number,希望这对于那些在SQL Server方面更有经验的人来说足够容易 我有一个客户贷款活动数据表,每当他们的帐户发生操作时,该表都会更新。例如,如果他们的限额增加,将使用他们的新限额创建一个新记录。我希望能够创建一个他们的活动列表,其中活动量是他们的新限额减去他们以前的限额 目前我有以下内容,但我正在努力找出如何访问以前的记录 SELECT CUSTOMER ,LEDGER ,ACCOUNT ,H.AMOUNT - COALESCE(X.AMOUNT, 0) F
SELECT
CUSTOMER
,LEDGER
,ACCOUNT
,H.AMOUNT - COALESCE(X.AMOUNT, 0)
FROM
dbo.ACTIVITY H WITH (NOLOCK)
LEFT OUTER JOIN
(SELECT
CUSTOMER
,LEDGER
,ACCOUNT
,ACTIVITY_DATE
,AMOUNT
,ROW_NUMBER() OVER (PARTITION BY CUSTOMER, LEDGER, ACCOUNT ORDER BY ACTIVITY_DATE ASC) AS ROW_NUMBER
FROM
dbo.ACTIVITY WITH (NOLOCK)) X ON H.CUSTOMER = X.CUSTOMER
AND H.LEDGER = X.LEDGER
AND H.ACCOUNT = X.ACCOUNT
因此,基本上我只想减去x.amount
,如果它是以前的记录,但我不知道在什么时候发生的,我不知道该怎么做
我以为行号()
会对我有所帮助,但我还是有点困惑
希望你们很快收到你们的来信:)
干杯这里的查询只会通过
dbo.Activity
一次
SELECT H.CUSTOMER
,H.LEDGER
,H.ACCOUNT
,MAX(H.ACTIVITY_DATE) ACTIVITY_DATE
,SUM(CASE X.I WHEN 1 THEN AMOUNT ELSE -AMOUNT END) AMOUNT
FROM (SELECT CUSTOMER
,LEDGER
,ACCOUNT
,ACTIVITY_DATE
,AMOUNT
,ROW_NUMBER() OVER (PARTITION BY CUSTOMER, LEDGER, ACCOUNT ORDER BY ACTIVITY_DATE DESC) AS ROW_NUMBER
FROM dbo.ACTIVITY WITH (NOLOCK)
) H
CROSS JOIN (select 1 union all select 2) X(I)
WHERE ROW_NUMBER - X.I >= 0
GROUP BY H.CUSTOMER
,H.LEDGER
,H.ACCOUNT
,ROW_NUMBER - X.I;
这是我用来测试的一些数据的DDL/DML
CREATE TABLE dbo.ACTIVITY(CUSTOMER int, LEDGER int, ACCOUNT int, ACTIVITY_DATE datetime, AMOUNT int)
INSERT dbo.ACTIVITY select
1,2,3,GETDATE(),123 union all select
1,2,3,GETDATE()-1,16 union all select
1,2,3,GETDATE()-2,12 union all select
1,2,3,GETDATE()-3,1 union all select
4,5,6,GETDATE(),1000 union all select
4,5,6,GETDATE()-6,123 union all select
7,7,7,GETDATE(),99;
选择 更传统的方法是使用子查询获取前一行:
SELECT CUSTOMER, LEDGER, ACCOUNT, ACTIVITY_DATE,
AMOUNT - ISNULL((SELECT TOP(1) I.AMOUNT
FROM dbo.ACTIVITY I
WHERE I.CUSTOMER = O.CUSTOMER
AND I.LEDGER = O.LEDGER
AND I.ACCOUNT = O.ACCOUNT
AND I.ACTIVITY_DATE < O.ACTIVITY_DATE
ORDER BY I.ACTIVITY_DATE DESC), 0) AMOUNT
FROM dbo.ACTIVITY O
ORDER BY CUSTOMER, LEDGER, ACCOUNT, ACTIVITY_DATE;
哪个版本的SQL Server?2012有一个
LAG()
函数。谢谢Richard。我会试试的。嗨,Richard,你更传统的方法是我最后自己制定并采用的方法。我试图回答我自己的问题,但显然不能,因为我是个新手。谢谢你的帮助……)请记住勾选答案作为解决方案。顺便说一句,第一个解决方案虽然更难理解,但性能会更好
SELECT A.CUSTOMER, A.LEDGER, A.ACCOUNT, A.ACTIVITY_DATE,
A.AMOUNT - ISNULL(B.AMOUNT,0) AMOUNT
FROM (SELECT *, RN=ROW_NUMBER() OVER (partition by CUSTOMER, LEDGER, ACCOUNT
order by ACTIVITY_DATE ASC)
FROM dbo.ACTIVITY) A
LEFT JOIN (SELECT *, RN=ROW_NUMBER() OVER (partition by CUSTOMER, LEDGER, ACCOUNT
order by ACTIVITY_DATE ASC)
FROM dbo.ACTIVITY) B ON A.CUSTOMER = B.CUSTOMER
AND A.LEDGER = B.LEDGER
AND A.ACCOUNT = B.ACCOUNT
AND B.RN = A.RN-1 -- prior record
ORDER BY A.CUSTOMER, A.LEDGER, A.ACCOUNT, A.ACTIVITY_DATE;