Cursor Pagination (prev / next) with null values - mysql

I have a cursor pagination implemented with MySQL (version 8.0), which works fine as long as there are no null values involved.
Here's my example data (id is a random UUID, date is date, time is time):
id | date | time
--------------------------
68 | 2017-10-28 | 22:00:00
d3 | 2017-11-03 | null
dd | 2017-11-03 | 21:45:00
62 | 2017-11-04 | 14:00:00
a1 | 2017-11-04 | 19:40:00
The cursor I use always consists of all three columns.
I use this query to get the next results (after the cursor):
SELECT * FROM table
WHERE (date > cursor.date)
OR (date = cursor.date AND time > cursor.time)
OR (date = cursor.date AND time = cursor.time AND id > cursor.id)
ORDER BY date ASC, time ASC, id ASC
And this query for prev results (before the cursor):
SELECT * FROM table
WHERE (date < cursor.date)
OR (date = cursor.date AND time < cursor.time)
OR (date = cursor.date AND time = cursor.time AND id < cursor.id)
ORDER BY date DESC, time DESC, id DESC
When using the prev query with cursor [id = dd, date = 2017-11-03, time = 21:45:00] it won't return the row with id = d3, because time is null, and this won't get selected by time < cursor.time.
Though I tried using time < cursor.time OR time IS NULL instead of time < cursor.time to include rows with null values. Which seems to fix this particular problem, but then creates a new problem: When using the prev query with cursor [id = d3, date = 2017-11-03, time = null], because now the result contains the row of the provided cursor.
I hope there's an easy solution for this. There seems to be no examples or tutorials on the web that deal with null values in cursor pagination.
Note: For the solution it doesn't matter if null will be sorted before or after non-null values, as long as it's consistent. (MySQL's default ordering is null < non-null)

I am not going to touch the topic of using cursors for pagination. There are alternatives, such as limit/offset.
But my recommendation for your queries is to use coalesce(), assigning a fake time for the comparison. MySQL makes this somewhat simple, because it supports time values in excess of 24 hours. And those would not be valid values for a date/time combination.
So:
SELECT *
FROM table
WHERE (date > cursor.date) OR
(date = cursor.date AND COALESCE(time, '24:00:00') > COALESCE(cursor.time, '24:00:00')) OR
(date = cursor.date AND COALESCE(time, '24:00:00') = COALESCE(cursor.time, '24:00:00') AND id > cursor.id)
ORDER BY date ASC, time ASC, id ASC
A more concise WHERE clause would be:
WHERE (date, COALESCE(time, '24:00:00'), id) > (cursor.date, COALESCE(cursor.time, '24:00:00'), cursor.id)

I'm a bit late to the party but give the following a try. The cursor logic needs to be adjusted for nullable columns and when a cursor row returns a null value for the time column.
Both examples listed below:
declare #cursorID nvarchar(2)
declare #cursorDate date
declare #cursorTime time(0)
declare #table table(id nvarchar(2), date date, time time(0))
insert into #table
values
('68', '2017-10-28', '22:00:00'),
('d3', '2017-11-03', NULL),
('dd', '2017-11-03', '21:45:00'),
('62', '2017-11-04', '14:00:00'),
('a1', '2017-11-04', '19:40:00')
--IF SELECTING A ROW WITH A NON-NULL VALUE FOR TIME
set #cursorID = 'dd'
set #cursorDate = (select date from #table where id = #cursorID)
set #cursorTime = (select time from #table where id = #cursorID)
--ASCENDING CURSOR VALUES
select * from #table
where
date >= #cursorDate
and (date > #cursorDate or (time >= #cursorTime
and (time > #cursorTime or id > #cursorID)))
order by
date asc, time asc, id asc
--DESCENDING CURSOR VALUES
select * from #table
where
date <= #cursorDate
and (date < #cursorDate or ((time <= #cursorTime or time is null)
and ((time < #cursorTime or time is null) or id < #cursorID)))
order by
date desc, time desc, id desc
--IF SELECTING A ROW WITH A NON VALUE FOR TIME
set #cursorID = 'd3'
set #cursorDate = (select date from #table where id = #cursorID)
set #cursorTime = (select time from #table where id = #cursorID)
--ASCENDING CURSOR VALUES
select * from #table
where
date >= #cursorDate
and (date > #cursorDate or (time is not null
or (time is null and id > #cursorID)))
order by
date asc, time asc, id asc
--DESCENDING CURSOR VALUES
select * from #table
where
date <= #cursorDate
and (date < #cursorDate or (time is null
and (id < #cursorID)))
order by
date desc, time desc, id desc

Add another column to the table. Make it a DATETIME. Combine date and time into it when not NULL; combine date with some particular time when NULL. Then your cursor has two columns to work with and no nulls.
If you have a reasonably recent version of MySQL, you can use a "generated stored" column, thereby avoiding any code changes.
And be sure to have INDEX(datetime, id).

If you are using MySQL 8.0 then you can consider to use row_number() window funciton create an unique sequential id (rn) for each row. Then just pass the rn for current row to get the previous rows.
Schema and insert statements:
create table cursortable( id varchar(10), date date, time time);
insert into cursortable values('68' , '2017-10-28' , '22:00:00');
insert into cursortable values('d3' , '2017-11-03' , null);
insert into cursortable values('dd' , '2017-11-03' , '21:45:00');
insert into cursortable values('62' , '2017-11-04' , '14:00:00');
insert into cursortable values('a1' , '2017-11-04' , '19:40:00');
Query to get the result for fist time:
select *,row_number()over(order by date,time,id)rn from cursortable
Output:
id
date
time
rn
68
2017-10-28
22:00:00
1
d3
2017-11-03
null
2
dd
2017-11-03
21:45:00
3
62
2017-11-04
14:00:00
4
a1
2017-11-04
19:40:00
5
Query to get the previous rows for cursor [id = dd, date = 2017-11-03, time = 21:45:00, rn=3] with only cursor [rn=3]:
with cte as
(
select *,row_number()over(order by date,time,id)rn from cursortable
)
select * from cte where rn<3
Output:
id
date
time
rn
68
2017-10-28
22:00:00
1
d3
2017-11-03
null
2
db<>fiddle here
If you don't want to introduce an computed column into your code then please try the below solution considering all three columns cursor [id = dd, date = 2017-11-03, time = 21:45:00]
Query:
with cte as
(
select *,row_number()over(order by date,time,id)rn from cursortable
)
,cte2 as
(
select * from cte where id='dd' and date= '2017-11-03' and time= '21:45:00'
)
select cte.id,cte.date,cte.time from cte inner join cte2 on cte.rn<cte2.rn
Output:
id
date
time
68
2017-10-28
22:00:00
d3
2017-11-03
null
db<>fiddle here
Your code would be like below:
with cte as
(
select *,row_number()over(order by date,time,id)rn from cursortable
)
,cte2 as
(
select * from cte where id=cursor.id and date= cursor.date and time= cursor.time
)
select cte.id,cte.date,cte.time from cte inner join cte2 on cte.rn<cte2.rn

Related

Get recent count from a column

I would like to get the count of a column based on its recent status.
Please see table structure below:
id | visible | date
1 | 1 | 2021-07-22
2 | 1 | 2021-07-23
3 | 0 | 2021-07-24
4 | 1 | 2021-07-25
5 | 0 | 2021-07-26
6 | 0 | 2021-07-27
For example, if I query
SELECT COUNT(visible) AS latest_not_visible WHERE date = '2021-07-26'
then it should return
latest_not_visible
1
Since it only counts that date as not visible, it disregarded the count on 07/24 since 07/25 is visible
But if I query
SELECT COUNT(visible) AS latest_not_visible WHERE date = '2021-07-27'
latest_not_visible
2
since 07/26 and 07/27 are both non-visible and no date in between is visible
I already had the solution to the problem, but I would need help in optimizing this function:
IIF(datediff
(day,
(SELECT MAX(date) FROM t1 WHERE (visible = 0 OR visible = '-1' OR visible = '-3') AND item_id = vp.item_id AND [date] <= vp.date),
(SELECT MAX(date) FROM t1 WHERE visible = 1 AND item_id = vp.item_id AND [date] <= vp.date)) IS NULL
OR datediff(day,
(SELECT MAX(date) FROM t1 WHERE (visible = 0 OR visible = '-1' OR visible = '-3') AND item_id = vp.item_id AND [date] <= vp.date),
(SELECT MAX(date) FROM t1 WHERE visible = 1 AND item_id = vp.item_id AND [date] <= vp.date)) < 0,
(SELECT COUNT(1) FROM t1 WHERE (visible = 0 OR visible = '-1' OR visible = '-3') AND item_id = vp.item_id AND [date] <= vp.date), 0)
AS times_not_visible,
table vp is the original table same with t1
Rather than counting them, you're better to calculate the number of days between the last visible and not visible on or before that date. So something like this...
SELECT DATEDIFF(
SELECT MAX(date) FROM YourTable WHERE visible = 0 AND date <= '2021-07-27'),
SELECT MAX(date) FROM YourTable WHERE visible = 1 AND date <= '2021-07-27')
) as latest_not_visible;
Find the latest visible date earlier than the given date and count all rows in between those two dates:
SET #dt = '2021-07-25';
SELECT COUNT(*)
FROM t
WHERE date <= (SELECT date FROM t WHERE date = #dt AND visible = 0)
AND date > (SELECT date FROM t WHERE date < #dt AND visible = 1 ORDER BY date DESC LIMIT 1)
SQL Fiddle
A solution with GROUP_CONCAT():
SELECT CHAR_LENGTH(visible) - CHAR_LENGTH(TRIM(TRAILING '0' FROM visible)) latest_not_visible
FROM (
SELECT GROUP_CONCAT(visible ORDER BY date SEPARATOR '') visible
FROM tablename
WHERE date <= ?
) t
Change ? to the date you want.
See the demo.
You can use window functions:
select count(*)
from (select t.*,
max(case when visible = 1 then date end) over (order by date) as max_visible_date
from t
where date <= '2021-07-26' -- or whatever
) t
where visible = 0 and
(date > max_visible_date or max_visible_date is null);
Note that this version only mentions the date once. It also works for if there are no rows with visible = 1, and it works on any number of rows.

Get Data According to Group by date field

Here is my table
Which have field type which means 1 is for income and 2 is for expense
Now requirement is for example in table there is two transaction made on 2-10-2018 so i want data as following
Expected Output
id created_date total_amount
1 1-10-18 10
2 2-10-18 20(It calculates all only income transaction made on 2nd date)
3 3-10-18 10
and so on...
it will return an new field which contains only incom transaction made on perticulur day
What i had try is
SELECT * FROM `transaction`WHERE type = 1 ORDER BY created_date ASC
UNION
SELECT()
//But it wont work
SELECT created_date,amount,status FROM
(
SELECT COUNT(amount) AS totalTrans FROM transaction WHERE created_date = created_date
) x
transaction
You can Also See Schema HERE http://sqlfiddle.com/#!9/6983b9
You can Count() the total number of expense transactions using conditional function If(), on a group of created_date.
Similarly, you can Sum() the amount of expense done using If(), on a created_date.
Try the following:
SELECT
`created_date`,
SUM(IF (`type` = 2, `amount`, 0)) AS total_expense_amount,
COUNT(IF (`type` = 2, `id`, NULL)) AS expense_count
FROM
`transaction`
GROUP BY `created_date`
ORDER BY `created_date` ASC
Do you just want a WHERE clause?
SELECT t.created_date, SUM(amount) as total_amount
FROM transaction t
WHERE type = 2
GROUP BY t.created_date
ORDER BY created_date ASC ;

Display summary data for every month in SQL for last 3 years

I have this T-SQL query that would be the total count of claims, dollar value for the date declared.
But I need to find the count and dollar value for each month beginning starting 2016 and until today / yesterday. I want to load the result set to a new table. Any thoughts or suggestions? Thanks in advance!
T-SQL query
DECLARE #AsofDATE AS DATE
DECLARE #AsofDateINT AS INT
SET #AsofDATE = '1/1/2018'
SET #AsofDateINT = 20180101
SELECT
COUNT(S.ClaimNum) Count_of_Claims,
SUM(ReserveIndemnityAmount) AS RD_REserve,
#AsofDATE AS AsofDate
-- INTO #tempRD
FROM
(SELECT
f.*,
ROW_NUMBER() OVER (PARTITION BY ClaimNum ORDER BY f.ModifiedDate DESC) AS Row_order_desc
FROM
[dbo].[Snapshot] f
WHERE
CAST(f.ModifiedDate AS DATE) <= #AsofDATE) S
LEFT OUTER JOIN
(SELECT
ClaimKey, SUM( t.LossRsvAmt) AS ReserveIndemnityAmount
FROM
Stg.Claim_Transaction t
WHERE
TransactionDate < #AsofDateINT
GROUP BY
ClaimKey) T ON t.ClaimKey = s.ClaimID
WHERE
S.Row_order_desc = 1
AND S.DerivedClaimStatus NOT IN ('Closed', 'Cancelled', 'Abandoned', 'Record only', 'Opened in error' )
AND s.specialty = 'RD'
Current result:
Count_of_Claims RD_REserve AsofDate
-------------------------------------------------
15317 112192.15 2018-01-01
Expected result:
Count_of_Claims RD_REserve AsofDate
-------------------------------------------------
15317 112192.15 2017-01-12
15567 111592.15 2017-01-11
15356 15492.15 2017-01-10
Your AsofDate is hardcoded to return. Why not replace that with ModifiedDate?
so something like
select
count(s.claimnum) countofclaims
,sum(amount) amount
,cast(eomonth(modifieddate) as date) [asofdate]
from your query...
group by
cast(eomonth(modifieddate) as date)

Calculate Date by number of working days from a certain Startdate

I've got two tables, a project table and a calendar table. The first containts a startdate and days required. The calendar table contains the usual date information, like date, dayofweek, and a column is workingday, which shows if the day is a saturday, sunday, or bank holiday (value = 0) or a regular workday (value = 1).
For a certain report I need write a stored procedure that calculates the predicted enddate by adding the number of estimated workddays needed.
Example:
**Projects**
Name Start_Planned Work_days_Required
Project A 02.05.2016 6
Calendar (04.05 is a bank holdiday)
Day Weekday Workingday
01.05.2016 7 0
02.05.2016 1 1
03.05.2016 2 1
04.05.2016 3 0
05.05.2016 4 1
06.05.2016 5 1
07.05.2016 6 0
08.05.2016 7 0
09.05.2016 1 1
10.05.2016 2 1
Let's say, the estimated number of days required is given as 6 (which leads to the predicted enddate of 10.05.2016). Is it possible to join the tables in a way, which allows me to put something like
select date as enddate_predicted
from calendar
join projects
where number_of_days = 6
I would post some more code, but I'm quite stuck on how where to start.
Thanks!
You could get all working days after your first date, then apply ROW_NUMBER() to get the number of days for each date:
SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE IsWorkingDay = 1
AND Date >= #StartPlanned
Then it would just be a case of filtering for the 6th day:
DECLARE #StartPlanned DATE = '20160502',
#Days INT = 6;
SELECT Date
FROM ( SELECT Date, DayNum = ROW_NUMBER() OVER(ORDER BY Date)
FROM Calendar
WHERE WorkingDay = 1
AND Date >= #StartPlanned
) AS c
WHERE c.DayNum = #Days;
It's not part of the question, but for future proofing this is easier to acheive in SQL Server 2012+ with OFFSET/FETCH
DECLARE #StartPlanned DATE = '20160502',
#Days INT = 6;
SELECT Date
FROM dbo.Calendar
WHERE Date >= #StartPlanned
AND WorkingDay = 1
ORDER BY Date
OFFSET (#Days - 1) ROWS FETCH NEXT 1 ROWS ONLY
ADDENDUM
I missed the part earlier about having another table, and the comment about putting it into a cursor has prompted me to amend my answer. I would add a new column to your calendar table called WorkingDayRank:
ALTER TABLE dbo.Calendar ADD WorkingDayRank INT NULL;
GO
UPDATE c
SET WorkingDayRank = wdr
FROM ( SELECT Date, wdr = ROW_NUMBER() OVER(ORDER BY Date)
FROM dbo.Calendar
WHERE WorkingDay = 1
) AS c;
This can be done on the fly, but you will get better performance with it stored as a value, then your query becomes:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
INNER JOIN dbo.Calendar AS c1
ON c1.Date = p.Start_Planned
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
This simply gets the working day rank of your start date, and finds the number of days ahead specified by the project by joining on WorkingDayRank (-1 because you want the end date inclusive of the range)
This will fail, if you ever plan to start your project on a non working day though, so a more robust solution might be:
SELECT p.Name,
p.Start_Planned,
p.Work_days_Required,
EndDate = c2.Date
FROM Projects AS P
CROSS APPLY
( SELECT TOP 1 c1.Date, c1.WorkingDayRank
FROM dbo.Calendar AS c1
WHERE c1.Date >= p.Start_Planned
AND c1.WorkingDay = 1
ORDER BY c1.Date
) AS c1
INNER JOIN dbo.Calendar AS c2
ON c2.WorkingDayRank = c1.WorkingDayRank + p.Work_days_Required - 1;
This uses CROSS APPLY to get the next working day on or after your project start date, then applies the same join as before.
This query returns a table with a predicted enddate for each project
select name,min(day) as predicted_enddate from (
select c.day,p.name from dbo.Calendar c
join dbo.Calendar c2 on c.day>=c2.day
join dbo.Projects p on p.start_planned<=c.day and p.start_planned<=c2.day
group by c.day,p.work_days_required,p.name
having sum(c2.workingday)=p.work_days_required
) a
group by name
--This gives me info about all projects
select p.projectname,p.Start_Planned ,c.date,
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
now you can use CTE like below or wrap this in a procedure
;with cte
as
(
Select
p.projectnam
p.Start_Planned ,
c.date,datediff(days,p.Start_Planned,c.date) as nooffdays
from calendar c
join
projects o
on c.date=dateadd(days,p.Work_days_Required,p.Start_Planned)
and c.isworkingday=1
)
select * from cte where nooffdays=6
use below logic
CREATE TABLE #proj(Name varchar(50),Start_Planned date,
Work_days_Required int)
insert into #proj
values('Project A','02.05.2016',6)
CReATE TABLE #Calendar(Day date,Weekday int,Workingday bit)
insert into #Calendar
values('01.05.2016',7,0),
('02.05.2016',1,1),
('03.05.2016',2,1),
('04.05.2016',3,0),
('05.05.2016',4,1),
('06.05.2016',5,1),
('07.05.2016',6,0),
('08.05.2016',7,0),
('09.05.2016',1,1),
('10.05.2016',2,1)
DECLARE #req_day int = 3
DECLARE #date date = '02.05.2016'
--SELECT #req_day = Work_days_Required FROM #proj where Start_Planned = #date
select *,row_number() over(order by [day] desc) as cnt
from #Calendar
where Workingday = 1
and [Day] > #date
SELECT *
FROM
(
select *,row_number() over(order by [day] desc) as cnt
from #Calendar
where Workingday = 1
and [Day] > #date
)a
where cnt = #req_day

mysql query uses every row of another query

I have searched a lot, but cannot find a helpful answer:
i want to have a list of totals from a period the user defines by giving me a start and end date. The totals should every time being from the start date to beginning with the start date and add every row 1 day. so the last row gives the totals from start to end date.
example: - given period = start 2013-01-01 , end = 2013-01-31
total day 1 = 100
total day 2 = 0 (not listed in my totalsperday query, but should have a row in my final query)
total day 3 = 140
total day 4 = 20
...
final table should look like:
end day 1: 100
end day 2: 100
end day 3: 240
end day 4: 260
...
so i have a query who calculates all days:
SELECT '2013-01-01' as startdate, w.endDate
FROM
(
SELECT date('2013-01-01' + INTERVAL u.i*100 + v.i*10 + w.i DAY) AS endDate
FROM sysints AS u
JOIN sysints AS v
JOIN sysints AS w
WHERE ( u.i*100 + v.i*10 + w.i ) <=
(
SELECT DATEDIFF( '2013-01-31','2013-01-01') as ddff
)
) w
ORDER BY w.endDate ASC
and i have a query who calculates the totals per day
SELECT p.selldate, SUM(p.price) as totalPerDay
FROM products p
WHERE '2013-01-01' >= p.selldate <= '2013-01-31'
GROUP BY p.selldate
ORDER BY p.selldate ASC
now combining these two to get my final result is hard.
basically what the final query should look like is:
- make the sum of sumperday from day 1 to day 1
- make the sum of sumperday from day 1 to day 2
- make the sum of sumperday from day 1 to day 3
...
any help?
thx.
this is a simplified example of my final query.
Below is the sample. The idea is to obtain a initial data set ordered by date and having aggregate totals, implicit date range records. Then using the cursor you can pass through each row to get the final total column (amountCalc column in the sample) just by summarize the previous records - will work because you already have the columns ordered by date.
The procedure can have other input/ output parameters. Instead of getting info from table you can get data from one view, where the view can be already order by date asc. Is just a sample so can be customized as needed.
Good luck.
-- drop table `Balance`;
CREATE TABLE `Balance` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`account` varchar(30) NOT NULL,
`amount` DECIMAL(10,2) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `Balance` (`date`, `account`, `amount`) VALUES
('2013-01-02', 'T355176', 8700),
('2013-01-03', 'T355176', 8900),
('2013-01-04', 'T355215', 33308),
('2013-01-03', 'T355215', 116581),
('2013-01-06', 'T812022', 275000),
('2013-01-02', 'T812063', 136500),
('2013-01-05', 'T812063', 11682),
('2013-01-06', 'T812064', 615100),
('2013-01-03', 'T812064', 25000),
('2013-01-02', 'T812085', 82500);
SELECT * FROM Balance WHERE date >= '2013-01-01' AND date <= '2013-01-06' ORDER BY date ASC;
CALL sp_getTotals('2013-01-01', '2013-01-06');
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `sp_getTotals`(IN startDate DATE, IN endDate DATE)
BEGIN
DECLARE dt DATE;
DECLARE amt DECIMAL(10,2);
DECLARE amtCalcPart DECIMAL(10,2);
DECLARE done INT DEFAULT 0;
DECLARE dtStart DATE;
DECLARE dtEnd DATE;
DECLARE cur1 CURSOR FOR SELECT date, amount FROM `TempMB`;
DECLARE cur2 CURSOR FOR SELECT startDate, endDate;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS `TempMB`;
CREATE TEMPORARY TABLE IF NOT EXISTS `TempMB` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`amount` DECIMAL(10,2) NULL DEFAULT 0.00,
`amountCalc` DECIMAL(10,2) NULL DEFAULT 0.00,
PRIMARY KEY (`id`)
);
SET dtStart = DATE(startDate);
SET dtEnd = DATE(endDate);
WHILE dtStart <= dtEnd DO
INSERT INTO `TempMB` (`date`) SELECT dtStart;
SET dtStart = DATE_ADD(dtStart, INTERVAL 1 DAY);
END WHILE;
SELECT * FROM TempMB;
-- Fill temp table with info needed
UPDATE `TempMB` t
INNER JOIN
(
SELECT date, SUM(amount) AS amount
FROM Balance
WHERE
date >= startDate AND date <= endDate
GROUP BY date
ORDER BY date ASC
) b ON b.date = t.date
SET
t.amount = b.amount;
/*INSERT INTO `TempMB` (`date`, `amount`)
SELECT date, SUM(amount) AS amount
FROM Balance
WHERE
date >= startDate AND date <= endDate
GROUP BY date
ORDER BY date ASC;
*/
SET amtCalcPart = 0.00;
-- Initialise cursor
OPEN cur1;
-- USE BEGIN-END handler for cursor-control within own BEGIN-END block
BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
-- Loop cursor throu temp records
LOOP
-- Get next value
FETCH cur1 INTO dt, amt;
-- Calculate amountCalc
SET amtCalcPart = (SELECT SUM(amount) as amt FROM `TempMB` WHERE Date <= dt);
UPDATE `TempMB` SET amountCalc = amtCalcPart WHERE date = dt;
END LOOP;
END;
-- Release cursor
CLOSE cur1;
SELECT * FROM TempMB;
END