Data as follows in my table
SELECT ID, VALUE, acc_no, adate
FROM TB_DailyStatement
id value acc_no adate
---------------------------------------------
1 12 1 2019-01-01 07:40:38.250
2 14 1 2019-01-02 07:41:05.883
3 15 1 2019-01-13 07:41:22.377
4 10 2 2019-01-14 08:15:53.403
5 16 2 2019-01-03 13:52:47.347
6 19 1 2019-01-09 13:53:56.317
7 7 3 2019-01-17 00:00:00.000
8 24 2 2019-01-17 00:00:00.000
9 19 2 2019-01-02 00:00:00.000
10 7 1 2019-01-07 00:00:00.000
11 24 1 2019-01-05 14:12:47.080
12 20 3 2019-01-28 00:00:00.000
Expected result
id value acc_no aDATE result
------------------------------------------------------------------------
1 12 1 2019-01-01 07:40:38.250 12 (current row values of acc_no=1)
2 14 1 2019-01-02 07:41:05.883 2 (14 (current row values)-12(previous row value of acc_no=1))
11 24 1 2019-01-05 14:12:47.080 10 (24 (current row values)-14(previous date value of acc_no=1))
10 7 1 2019-01-07 00:00:00.000 -17 (7 (current row values)-24(previous date value of acc_no=1))
6 19 1 2019-01-09 13:53:56.317 12 (19 (current row values)-7(previous date value of acc_no=1))
3 15 1 2019-01-13 07:41:22.377 -4 (15 (current row values)-19(previous date value of acc_no=1))
9 19 2 2019-01-02 00:00:00.000 19 (12 (current row values of acc_no=2)
5 16 2 2019-01-03 13:52:47.347 -3 (16 (current row values)-14(previous date value of acc_no=2))
4 10 2 2019-01-14 08:15:53.403 -6 (10 (current row values)-16(previous date value of acc_no=2))
8 24 2 2019-01-17 00:00:00.000 14 (24 (current row values)-10(previous date value of acc_no=2))
7 7 3 2019-01-17 00:00:00.000 7 (12(current row values of acc_no=3)
12 20 3 2019-01-28 00:00:00.000 13 (20 (current row values)-7(previous date value of acc_no=3))
I have tried the following query
SELECT
id, t.value, acc_no, adate,
t.value - ISNULL(v.value, 0) AS result
FROM
TB_DailyStatementt
OUTER APPLY
(SELECT TOP (1) value
FROM TB_DailyStatement
WHERE id < t.id
AND acc_no = t.acc_no
ORDER by id DESC) v
This returns some output, but I am not able to use order by clause ie adate and acc_no
If you want to get this result just simple order by acc_no asc you can get simple your expected result,
For example
Select * from table order by acc_no acs
In SQL Server 2008
, you can't use LEAD & LAG
, for this you can use query like following using OUTER APPLY
.
select *
from TB_DailyStatementt tout
outer apply (select top 1 value Prev
from TB_DailyStatementt t1
where t1.acc_no = tout.acc_no
AND t1.adate < tout.adate
order by t1.adate desc)t1
outer apply (select top 1 value Next
from TB_DailyStatementt t1
where t1.acc_no = tout.acc_no
AND t1.adate > tout.adate
order by t1.adate asc)t2
order by tout.adate,acc_no
This will give you the required previous and next values depending on acc_no. Now you can apply switch case to format the string.
Check this Demo
Declare @ds TABLE (id int, value int, acc_no int, dt datetime)
INSERT INTO @ds
SELECT 1, 12, 1, '2019-01-01 07:40:38.250' UNION
SELECT 2, 14, 1, '2019-01-02 07:41:05.883' UNION
SELECT 3, 15, 1, '2019-01-13 07:41:22.377' UNION
SELECT 4, 10, 2, '2019-01-14 08:15:53.403' UNION
SELECT 5, 16, 2, '2019-01-03 13:52:47.347' UNION
SELECT 6, 19, 1, '2019-01-09 13:53:56.317' UNION
SELECT 7, 7, 3, '2019-01-17 00:00:00.000' UNION
SELECT 8, 24, 2, '2019-01-17 00:00:00.000' UNION
SELECT 9, 19, 2, '2019-01-02 00:00:00.000' UNION
SELECT 10, 7, 1, '2019-01-07 00:00:00.000' UNION
SELECT 11, 24, 1, '2019-01-05 14:12:47.080' UNION
SELECT 12, 20, 3, '2019-01-28 00:00:00.000'
SELECT id, value, acc_no, dt, value - previous AS result
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY DS1.id
ORDER BY DS2.dt DESC) AS rn
,DS1.*, COALESCE(DS2.value,0) AS previous
FROM @ds DS1
LEFT JOIN @ds DS2
ON DS2.acc_no = DS1.acc_no
AND DS2.dt < DS1.dt
) AS dt
WHERE rn = 1
In your original query, you are joining on ID, the your comments in the desired results show that you want to use the date for ordering, not the id.
So you could fix your original query by changing "id < t.id" with "adate < t.adate"
I think you are on the right track. You need an order by
in the outer query and to fix the table aliases:
SELECT ds.id, ds.value, ds.acc_no, ds.adate,
(t.value - COALESCE(prev.value, 0)) AS result
FROM TB_DailyStatementt ds OUTER APPLY
(SELECT TOP (1) ds2.value
FROM TB_DailyStatement ds2
WHERE ds2.id < ds.t.id AND ds2.acc_no = ds.acc_no
ORDER by ds2.id DESC
) prev
ORDER BY ds.acc_no, ds.adate
Try this:
Select *, CASE WHEN LAG(value) OVER(partition by acc_no order by adate) IS NULL THEN value
ELSE value - LAG(value) OVER(partition by acc_no order by adate) END result from TB_DailyStatement
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.