Null Values during Query - mysql

I have the below table, pretty simple.
==========================================================================
attendanceID | agentID | incurredDate | points | comment
==========================================================================
10 | vimunson | 2013-07-22 | 2 | Some Text
11 | vimunson | 2013-07-29 | 2 | Some Text
12 | vimunson | 2013-12-06 | 1 | Some Text
The his query below:
SELECT
attendanceID,
agentID,
incurredDate,
leadDate,
points,
#1F:=IF(incurredDate <= curdate() - 90
AND leadDate = NULL,
points - 1,
IF(DATEDIFF(leadDate, incurredDate) > 90,
points - 1,
points)) AS '1stFallOff',
#2F:=IF(incurredDate <= curdate() - 180
AND leadDate = NULL,
points - 2,
IF(DATEDIFF(leadDate, incurredDate) > 180,
points - 2,
#1F)) AS '2ndFallOff',
IF(#total < 0, 0, #total:=#total + #2F) AS Total,
comment,
linked
FROM
(SELECT
attendanceID,
mo.agentID,
#r AS leadDate,
(#r:=incurredDate) AS incurredDate,
comment,
points,
linked
FROM
(SELECT
m . *
FROM
(SELECT #_date = NULL, #total:=0) varaible, attendance m
ORDER by agentID , incurredDate desc) mo
where
agentID = 'vimunson'
AND (case
WHEN #_date is NULL or #_date <> incurredDate THEN #r:=NULL
ELSE NULL
END IS NULL)
AND (#_date:=incurredDate) IS NOT NULL) T
ORDER BY agentID , incurredDate
When I run the query it returns the below:
========================================================================================================================================
attendanceID | agentID | incurredDate | leadDate | points | 1stFallOff | 2ndFallOff | Total | comment
========================================================================================================================================
10 | vimunson | 2013-07-22 | NULL | 2 | 2 | 2 | 2 | Some Text
11 | vimunson | 2013-07-29 | NULL | 2 | 2 | 2 | 4 | Some Text
12 | vimunson | 2013-12-06 | NULL | 1 | 2 | 1 | 5 | Some Text
I cannot figure out why the leadDate column is `null'. I have narrowed it down to a user session. For example if I run it again with the same user session it will come back with what I want.

The way variables #r and #_date are passed around relies on a specific order in which certain parts of the query are evaluated. That's a risky assumption to make in a query language that is declarative rather than imperative. The more sophisticated a query optimizer is, the more unpredictable the behaviour of this query will be. A 'simple' engine might follow your intentions, another engine might adapt its behaviour as you go, for example because it uses temporary indexes to improve query performance.
In situations where you need to pass values from one row to another, it would be better to use a cursor.
http://dev.mysql.com/doc/refman/5.0/en/cursors.html
EDIT: sample code below.
I focused on column 'leadDate'; implementation of the falloff and total columns should be similar.
CREATE PROCEDURE MyProc()
BEGIN
DECLARE done int DEFAULT FALSE;
DECLARE currentAttendanceID int;
DECLARE currentAgentID, previousAgentID varchar(8);
DECLARE currentIncurredDate date;
DECLARE currentLeadDate date;
DECLARE currentPoints int;
DECLARE currentComment varchar(9);
DECLARE myCursor CURSOR FOR
SELECT attendanceID, agentID, incurredDate, points, comment
FROM attendance
ORDER BY agentID, incurredDate DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CREATE TEMPORARY TABLE myTemp (
attendanceID int,
agentID varchar(8),
incurredDate date,
leadDate date,
points int,
comment varchar(9)
) ENGINE=MEMORY;
OPEN myCursor;
SET previousAgentID := NULL;
read_loop: LOOP
FETCH myCursor INTO currentAttendanceID, currentAgentID, currentIncurredDate, currentPoints, currentComment;
IF done THEN
LEAVE read_loop;
END IF;
IF previousAgentID IS NULL OR previousAgentID <> currentAgentID THEN
SET currentLeadDate := NULL;
SET previousAgentID := currentAgentID;
END IF;
INSERT INTO myTemp VALUES (currentAttendanceID, currentAgentID, currentIncurredDate, currentLeadDate, currentPoints, currentComment);
SET currentLeadDate := currentIncurredDate;
END LOOP;
CLOSE myCursor;
SELECT *
FROM myTemp
ORDER BY agentID, incurredDate;
DROP TABLE myTemp;
END
FYC: http://sqlfiddle.com/#!2/910a3/1/0

Try this:
SELECT a.attendanceID, a.agentID, a.incurredDate, a.leadDate, a.points,
#1F:= (CASE WHEN incurredDate <= CURDATE()-90 AND leadDate=NULL THEN points-1
WHEN DATEDIFF(leadDate, incurredDate) > 90 THEN points-1
ELSE points
END) AS '1stFallOff',
#2F:= (CASE WHEN incurredDate <= CURDATE()-180 AND leadDate=NULL THEN points-2
WHEN DATEDIFF(leadDate, incurredDate) > 180 THEN points-2
ELSE #1F
END) AS '2ndFallOff',
(#Total:=#Total + a.points) AS Total, a.comment
FROM (SELECT a.attendanceID, a.agentID, a.incurredDate, b.incurredDate leadDate, a.points, a.comment
FROM attendance a
LEFT JOIN attendance b ON a.agentID = b.agentID AND a.incurredDate < b.incurredDate
GROUP BY a.agentID, a.incurredDate
) AS A, (SELECT #Total:=0, #1F:=0, #2F:=0) B;
Check the SQL FIDDLE DEMO
OUTPUT
| ATTENDANCEID | AGENTID | INCURREDDATE | LEADDATE | POINTS | 1STFALLOFF | 2NDFALLOFF | TOTAL | COMMENT |
|--------------|----------|---------------------------------|---------------------------------|--------|------------|------------|-------|-----------|
| 10 | vimunson | July, 22 2013 00:00:00+0000 | July, 29 2013 00:00:00+0000 | 2 | 2 | 2 | 2 | Some Text |
| 11 | vimunson | July, 29 2013 00:00:00+0000 | December, 06 2013 00:00:00+0000 | 2 | 1 | 1 | 4 | Some Text |
| 12 | vimunson | December, 06 2013 00:00:00+0000 | (null) | 1 | 1 | 1 | 5 | Some Text |

After reviewing multiple results I was able to come up with something that is what I expect. I have entered more data and the below syntax. I liked the idea of the cursor but it was not ideal for my use, so I did not use it. I did not want to use CASE or any JOINS since they can be complex.
http://sqlfiddle.com/#!2/2fb86/1
SELECT
attendanceID,
agentID,
incurredDate,
#ld:=(select
incurredDate
from
attendance
where
incurredDate > a.incurredDate
and agentID = a.agentID
order by incurredDate
limit 1) leadDate,
points,
#1F:=IF(incurredDate <= DATE_SUB(curdate(),
INTERVAL IF(incurredDate < '2013-12-02', 90, 60) DAY)
AND #ld <=> NULL,
points - 1,
IF(DATEDIFF(COALESCE(#ld, '1900-01-01'),
incurredDate) > IF(incurredDate < '2013-12-02', 90, 60),
points - 1,
points)) AS '1stFallOff',
#2F:=IF(incurredDate <= DATE_SUB(curdate(),
INTERVAL IF(incurredDate < '2013-12-02',
180,
120) DAY)
AND getLeadDate(incurredDate, agentID) <=> NULL,
points - 1,
IF(DATEDIFF(COALESCE(#ld, '1900-01-01'),
incurredDate) > IF(incurredDate < '2013-12-02',
180,
120),
points - 2,
#1F)) AS '2ndFallOff',
IF((#total + #2F) < 0,
0,
IF(DATE_ADD(incurredDate, INTERVAL 365 DAY) <= CURDATE(),
#total:=0,
#total:=#total + #2F)) AS Total,
comment,
linked,
DATE_ADD(incurredDate, INTERVAL 365 DAY) AS 'fallOffDate'
FROM
(SELECT #total:=0) v,
attendance a
WHERE
agentID = 'vimunson'
GROUP BY agentID , incurredDate

Related

MySQL calculate moving average of N rows

I'm trying to calculate the moving average of N rows, for all rows in a single query. In the example case, I am attempting to calculate the moving average of 50 rows.
SELECT
h1.date,
h1.security_id,
( SELECT
AVG(last50.close)
FROM (
SELECT h.close
FROM history as h
WHERE h.date <= h1.date AND h.security_id = h1.security_id
ORDER BY h.date DESC
LIMIT 50
) as last50
) as avg50
FROM history as h1
However, MySQL gives me an error when running this query:
Unknown column 'h1.date' in 'where clause'
I'm trying this method because the other solutions listed don't really seem to work for my use case. There are solutions for a moving average of N days, but since all dates are not accounted for in my data set, I need the average of N rows.
This solution, shown below, doesn't work because AVG (also SUM and COUNT) doesn't account for LIMIT:
SELECT
t1.data_date
( SELECT SUM(t2.price) / COUNT(t2.price)
FROM t as t2
WHERE t2.data_date <= t1.data_date
ORDER BY t2.data_date DESC
LIMIT 5
) AS 'five_row_moving_average_price'
FROM t AS t1
ORDER BY t1.data_date;
This question looks promising, but is somewhat indecipherable to me.
Any suggestions? Here's an SQLFiddle to play around in.
plan
self join history on last 50 days
take average grouping by date and security id ( of current )
query
select curr.date, curr.security_id, avg(prev.close)
from history curr
inner join history prev
on prev.`date` between date_sub(curr.`date`, interval 49 day) and curr.`date`
and curr.security_id = prev.security_id
group by 1, 2
order by 2, 1
;
output
+---------------------------+-------------+--------------------+
| date | security_id | avg(prev.close) |
+---------------------------+-------------+--------------------+
| January, 04 2016 00:00:00 | 1 | 10.770000457763672 |
| January, 05 2016 00:00:00 | 1 | 10.800000190734863 |
| January, 06 2016 00:00:00 | 1 | 10.673333485921225 |
| January, 07 2016 00:00:00 | 1 | 10.59250020980835 |
| January, 08 2016 00:00:00 | 1 | 10.432000160217285 |
| January, 11 2016 00:00:00 | 1 | 10.40166680018107 |
| January, 12 2016 00:00:00 | 1 | 10.344285828726631 |
| January, 13 2016 00:00:00 | 1 | 10.297500133514404 |
| January, 14 2016 00:00:00 | 1 | 10.2877779006958 |
| January, 04 2016 00:00:00 | 2 | 56.15999984741211 |
| January, 05 2016 00:00:00 | 2 | 56.18499946594238 |
| .. | .. | .. |
+---------------------------+-------------+--------------------+
sqlfiddle
reference
sql rolling averages
modified to use last 50 rows
select
rnk_curr.`date`, rnk_curr.security_id, avg(rnk_prev50.close)
from
(
select `date`, security_id,
#row_num := if(#lag = security_id, #row_num + 1,
if(#lag := security_id, 1, 1)) as row_num
from history
cross join ( select #row_num := 1, #lag := null ) params
order by security_id, `date`
) rnk_curr
inner join
(
select date, security_id, close,
#row_num := if(#lag = security_id, #row_num + 1,
if(#lag := security_id, 1, 1)) as row_num
from history
cross join ( select #row_num := 1, #lag := null ) params
order by security_id, `date`
) rnk_prev50
on rnk_curr.security_id = rnk_prev50.security_id
and rnk_prev50.row_num between rnk_curr.row_num - 49 and rnk_curr.row_num
group by 1,2
order by 2,1
;
sqlfiddle
note
the if function is to force the correct order of evaluation of variables.
In mysql 8 window function frame can be used to obtain the averages.
SELECT date, security_id, AVG(close) OVER (PARTITION BY security_id ORDER BY date ROWS 49 PRECEDING) as ma
FROM history
ORDER BY date DESC
This calculates the average of the current row and 49 preceding rows.

Never decreasing cumulative figure

CREATE TABLE `test` (
`UniqueID` INT(11) NOT NULL AUTO_INCREMENT,
`Date` date,
`Entry` VARCHAR(20),
PRIMARY KEY (`UniqueID`)
);
INSERT INTO `test` (Date,Entry) VALUES
('2015-09-01','text1'),
('2015-09-01','text1'),
('2015-09-01','text1'),
('2015-09-02','text2'),
('2015-09-02','text2'),
('2015-09-02','text2'),
('2015-09-02','text2'),
('2015-09-03','text3'),
('2015-09-03','text3'),
('2015-09-03','text3'),
('2015-09-04','text4'),
('2015-09-04','text4'),
('2015-09-04','text4'),
('2015-09-04','text4'),
('2015-09-04','text4'),
('2015-09-04','text4');
SET #total:= 0;
SET #prevCount:= 0;
SELECT
#total:= IF (#prevCount <= COUNT(Entry),#total + (COUNT(Entry) - #prevCount),#total) AS total,
#prevCount := COUNT(Entry) AS dayTotal,
`Entry`,
`Date`
FROM test
GROUP BY `Date`
ORDER BY `Date` ASC
| total | dayTotal | Entry | Date |
|-------|----------|-------|-----------------------------|
| 3 | 3 | text1 | September, 01 2015 00:00:00 |
| 4 | 4 | text2 | September, 02 2015 00:00:00 |
| 3 | 3 | text3 | September, 03 2015 00:00:00 |
| 6 | 6 | text4 | September, 04 2015 00:00:00 |
fiddle of same: http://sqlfiddle.com/#!9/d9031/2
I need the total figure to never decrease because it is a cumulative figure over time.
My problem seems to be that MySQL doesn't store #prevCount on the loop - so I can't use it to calculate the total.
What I expect to see is that total will show
3
4
4
7
Note that the 7 is correct because it is the 4 plus the 3 new entries on the 4th.
Doing calculations with variables is tricky. With group by, you need to use a subquery.
Your logic doesn't make full sense to me. The closest reasonable thing I can think of is a cumulative max:
SELECT #max := if(#max > dayTotal, #max, dayTotal)
FROM (SELECT `Date`, COUNT(*) as dayTotal
FROM test
GROUP BY `Date`
) t CROSS JOIN
(SELECT #max := 0) params
ORDER BY `Date` ASC;
Note: I removed Entry because it is not in the GROUP BY.

MySQL Custom calculate views

I am having difficulty trying to combine a set of queries I am using. I currently am having to execute multiple queries with different years and CID numbers. (CID is 1-5, Years are CurrentYear to CurrentYear-6)
Current SQL Statement:
SELECT
1 as CID,
2015 as `Year`,
( SELECT SUM( legacy_reports_payments.AmountPaid ) * -1 AS Payments FROM legacy_reports_payments
WHERE DatePaid >= "2015-01-01 00:00:00" AND DatePaid < "2015-02-01 00:00:00"
AND CID = 1) As PaymentsJan,
( SELECT SUM( legacy_reports_payments.AmountPaid ) * -1 AS Payments FROM legacy_reports_payments
WHERE DatePaid >= "2015-02-01 00:00:00" AND DatePaid < "2015-03-01 00:00:00"
AND CID = 1) As PaymentsFeb,
( SELECT SUM( legacy_reports_payments.AmountPaid ) * -1 AS Payments FROM legacy_reports_payments
WHERE DatePaid >= "2015-03-01 00:00:00" AND DatePaid < "2015-04-01 00:00:00"
AND CID= 1) As PaymentsMar,
...
This returns:
CID | Year | PaymentsJan | PaymentsFeb | ...
1 | 2015 | 3000.00 | 3000.00 | ...
I want to create a single view that can show all of the calculated information, instead of running several queries like the one above.
I would like to have the view look more like this:
CID | Year | PaymentsJan | PaymentsFeb | ...
1 | 2015 | 3000.00 | 3000.00 | ...
2 | 2015 | 2000.00 | 2000.00 | ...
3 | 2015 | 5000.00 | 5000.00 | ...
1 | 2014 | 1000.00 | 3000.00 | ...
2 | 2014 | 3000.00 | 4000.00 | ...
3 | 2014 | 2000.00 | 5000.00 | ...
Can anyone provide any insight on the best way to handle this?
You could build a temporary table with the Years and CIDs you need and then join your query on that to do all of them at one. That many sub queries will be slow, but better than doing each one manually.
create table #Dates
(
controlCID int
,controlYear varchar(4)
)
DECLARE #year int = YEAR( getDate() )
DECLARE #numYears int = 6
DECLARE #numCID int = 5
DECLARE #CIDcounter int
while (#numYears > 0)
BEGIN
SET #CIDcounter = #numCID
while (#CIDcounter > 0)
BEGIN
insert into #Dates values ( #CIDcounter, (#year - #numYears + 1))
SET #CIDcounter = #CIDcounter - 1
END
SET #numYears = #numYears -1
END
select controlCID
,controlYear
--,( SELECT SUM( legacy_reports_payments.AmountPaid ) * -1 AS Payments FROM legacy_reports_payments
--WHERE p.DatePaid >= (controlYear+'-01-01 00:00:00') AND p.DatePaid < (controlYear+'-02-01 00:00:00')
--AND p.CID = controlCID) As PaymentsJan,
--etc and so on...
from #Dates
order by controlYear desc, controlCID
drop table #Dates
Just use the year and CID from the table in the sub queries and you should be good to go.

MySQL Conditions from Multiple Rows

I have been trying to calculate a table using a SELECT statement. I have a table like this:
--------------------------------------------------------------
AgentID | Date | Incurred | FallOffDate
==============================================================
kegomez | 2012-11-19 | 2.0 | 2013-11-19
kegomez | 2012-11-24 | 0.5 | 2013-11-24
kegomez | 2013-01-21 | 2.0 | 2014-01-21
kegomez | 2013-08-18 | 2.0 | 2014-08-18
I was trying to do the calculations on during the select and possibly create a view but have no luck so far. In the end the table will look like this.
--------------------------------------------------------------
AgentID | Date | Incurred | 90 | 180 | Total | FallOffDate
==============================================================
kegomez | 2012-11-19 | 2.0 | 2.0 | 2.0 | 2.0 | 2013-11-19
kegomez | 2012-11-24 | 0.5 | 0.5 | 0.5 | 2.5 | 2013-11-24
kegomez | 2013-01-21 | 2.0 | 1.0 | 0.0 | 2.5 | 2014-01-21
kegomez | 2013-08-18 | 2.0 | 2.0 | 2.0 | 4.5 | 2014-08-18
The total column uses values from the previous row to calculate its values. For example the date in row 4 will need to reference the date in row 3 to see if the date is greater. Would I need to try this with a subquery? How this will eventually work is that every 90 days up to 180 days the agent will loose 1 point if no more are incurred. Thus the reason why I need to reference other rows. If it helps this data is currently in Excel but is getting too large to manage and we need to move it over to something that performs better.
SELECT AgentID, Date, Incurred,
#90 := IF(Date<=CURDATE()-90 AND #r=0, Incurred-1.0, IF(Difference>90, Incurred-1, Incurred)) AS 90Day,
#180 := IF(Date<=CURDATE()-90 AND #r=0, Incurred-1.0, IF(Difference>180, Incurred-2, #90)) AS 180Day,
#Total := IF(#180<0,0,IF(FallOffDate<=CURDATE(),0, #180)) AS Total,
FallOffDate
FROM (SELECT mo.AgentID, mo.Incurred, FallOffDate,
#r AS LEAD_date,
DATEDIFF(#r,Date) AS Difference,
(#r := Date) AS Date
FROM (
SELECT m.*
FROM (
SELECT #_date = NULL
) VARIABLE,
attendance m
ORDER BY
AgentID, Date DESC
) mo
WHERE (CASE WHEN #_date IS NULL OR #_date <> date THEN #r := NULL ELSE NULL END IS NULL)
AND (#_date := date) IS NOT NULL) T
ORDER BY AgentID, Date;
Yes, you need to do this with a subquery, try with something like this (if you want the 4th row to access the date in 3rd row):
SELECT mo.AgentID, mo.date,
#r AS 'LAG(date)',
(case when #r<Date then 'YES' when #r is null then 'IS NULL' else 'NO' end) 'Is Bigger',
(#r := Date) AS Date
FROM (
SELECT m.*
FROM (
SELECT #_date = NULL
) variable,
data m
ORDER BY
AgentID
) mo
WHERE (CASE WHEN #_date IS NULL OR #_date <> date THEN #r := NULL ELSE NULL END IS NULL)
AND (#_date := date) IS NOT NULL
You can see a working demo here
Or you can try this query if you want that 3rd row has access to date in 4th row
SELECT AgentID,date,LEAD_date,concat(Difference,' days') FROM
(SELECT mo.AgentID,
#r AS LEAD_date,
DATEDIFF(#r,Date) as Difference,
(#r := Date) AS Date
FROM (
SELECT m.*
FROM (
SELECT #_date = NULL
) variable,
data m
ORDER BY
AgentID,date desc
) mo
WHERE (CASE WHEN #_date IS NULL OR #_date <> date THEN #r := NULL ELSE NULL END IS NULL)
AND (#_date := date) IS NOT NULL) T
order by AgentID,date;
You can see a working demo here

MYSQL query winning streak including score

I have a query-generated table that counts up the winning streak as long as the player keeps winning. When they player gets a positive score, the streak rises with 1, if he gets a negative score, the streak falls back to 0. The table looks like this:
+--------+------------------+--------+--------+
| player | timestamp | points | streak |
+--------+------------------+--------+--------+
| John | 22/11/2012 23:01 | -2 | 0 |
| John | 22/11/2012 23:02 | 3 | 1 |
| John | 22/11/2012 23:04 | 5 | 2 |
| John | 22/11/2012 23:05 | -2 | 0 |
| John | 22/11/2012 23:18 | 15 | 1 |
| John | 23/11/2012 23:20 | 5 | 2 |
| Chris | 27/11/2012 22:12 | 20 | 1 |
| Chris | 27/11/2012 22:14 | -12 | 0 |
| Chris | 27/11/2012 22:17 | 4 | 1 |
| Chris | 27/11/2012 22:18 | -4 | 0 |
| Chris | 27/11/2012 22:20 | 10 | 1 |
| Chris | 27/11/2012 22:21 | 20 | 2 |
| Chris | 27/11/2012 22:22 | 90 | 3 |
+--------+------------------+--------+--------+
I would like to get the players maximum streak, which is easy to get ofcourse, but I would also like to include the points that the player scored in that particular streak. So, for the above example the result would have to look like this:
+--------+--------+-----------+
| player | points | maxstreak |
+--------+--------+-----------+
| John | 20 | 2 |
| Chris | 120 | 3 |
+--------+--------+-----------+
Any idea's of how I could achieve this? Thanks in advance!
I have not had a chance to actually try this, but is SHOULD work using mySQL Variables...
At the beginning, the inner-most query just queries from your scores table and forces the data in order of player and timestamp. From that, I have to process sequentially with MySQL variables. First thing... on each new record being processed, if I am on a different "Player" (which should ACTUALLY be based on an ID instead of name), I am resetting the streak, points, maxStreak, maxStreakPoints to zero, THEN setting the last user to whoever its about to process.
Immediately after that, I am checking for the streak status, points, etc...
Once all have been tabulated, I then use the OUTERMOST query to get on a per-player basis, what their highest max streak / max streak points.
SELECT
Final.Player,
MAX( Final.MaxStreak ) MaxStreak,
MAX( Final.MaxStreakPoints ) MaxStreakPoints
FROM
(
SELECT
PreOrd.Player,
PreOrd.TimeStamp,
PreOrd.Points,
#nStreak := case when PreOrd.Points < 0 then 0
when PreOrd.Player = #cLastPlayer then #nStreak +1
else 1 end Streak,
#nStreakPoints := case when #nStreak = 1 then PreOrd.Points
when #nStreak > 1 then #nStreakPoints + PreOrd.Points
else 0 end StreakPoints,
#nMaxStreak := case when PreOrd.Player != #cLastPlayer then #nStreak
when #nStreak > #nMaxStreak then #nStreak
else #nMaxStreak end MaxStreak,
#nMaxStreakPoints := case when PreOrd.Player != #cLastPlayer then #nStreakPoints
when #nStreak >= #nMaxStreak and #nStreakPoints > #nMaxStreakPoints then #nStreakPoints
else #nMaxStreakPoints end MaxStreakPoints,
#cLastPlayer := PreOrd.Player PlayerChange
FROM
( select
S.Player,
S.TimeStamp,
S.Points
from
Scores2 S
ORDER BY
S.Player,
S.TimeStamp,
S.`index` ) PreOrd,
( select
#nStreak := 0,
#nStreakPoints := 0,
#nMaxStreak := 0,
#nMaxStreakPoints := 0,
#cLastPlayer := '~' ) SQLVars
) as Final
group by
Final.Player
Now, this could give a false max streak points, such that on a single score the person has 90 points, then a streak of 1 for 10 points, 2 for 10 points, 3 for 10 points, 30 total.. Still thinking on that though... :)
Here's what I get when I add the index column as you've made available from data supplied
SQL Fiddle Showing my solution...
My recommendation is to store additional information when you calculate the streak. For instance, you could store the time stamp when the streak began.
A less-serious recommendation is to switch to another database, that supports window functions. This would be much easier.
The approach is to find when the streak began and then sum up everything between that time and the max streak. To do this, we'll use a correlated subquery:
select t.*,
(select max(timestamp) from t t2 where t2.timestamp <= t.timestamp and t2.player = t.player and t2.streak = 0
) as StreakStartTimeStamp
from t
where t.timeStamp = (select max(streak) from t t2 where t.player = t2.player)
Now, we will embed this query as a subquery, so we can add the appropriate times:
select t.player,
sum(s.points)
from t join
(select t.*,
(select max(timestamp) from t t2 where t2.timestamp <= t.timestamp and t2.player = t.player and t2.streak = 0
) as StreakStartTimeStamp
from t
where t.streak = (select max(streak) from t t2 where t.player = t2.player)
) s
on t.player = s.player
group by t.player
I haven't tested this query, so there are probably some syntax errors. However, the approach should work. You may want to have indexes on the table, on streak and timestamp for performance reasons.