How to find actual count from a rolling count in MySQL DB - mysql

I have a table where the count of a specific data goes up to 5 and then rolls over to 0, I would like to query the table which shows the actual count as shown below
Desired OutPut:
Dev_count
Actual_Count
1
1
2
2
3
3
4
4
5
5
0
6
1
7
2
8
3
9
4
10
5
11
0
12
I tried using a Trigger to update an additional column with actual count using below SQL script
CREATE TRIGGER insert_continuous_count BEFORE INSERT ON x_table
FOR EACH ROW SET
NEW.continuous_count = (SELECT continuous_count
FROM x_table
where device_id = NEW.device_id
order by No DESC LIMIT 1
) + 1;
Then I read somewhere that the trigger cannot update the same table which is already being used (for reading or writing) by the statement that invoked the function or trigger.
Is there any easier way to get the desired output?

I think you need something like this :
select dev_count,
#row_number:= #row_number + 1 as Actual_Count
from test_tbl
cross join (select #row_number := 0) x;
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/139
In MySQL 8+ you can use ROW_NUMBER function:
SELECT
dev_count,
ROW_NUMBER() OVER () as rn
FROM test_tbl
ORDER BY rn;
Demo: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/144

Related

How to select MAX/MIN in MySQL with dynamic between clause

Assume a table with two columns t (a string with TimeStamps) and v (decimal). For each t I want to query the MAXIMUM of the value v in a certain range defined by the current t.
How can i transfer below statement to proper SQL?
select t, max(v for t between t-2MIN and t+2min) from table_name;
Example:
Assume below table.
t
v
1
3
2
2
3
5
4
4
5
8
6
1
I need an SQL-statement which gives me (for e.g. a width 2: max(v for t between t-2 and t+2)) the following result
t
v
1
5
2
5
3
8
4
8
5
8
6
8
Join the table with itself using the range as the joining condition.
SELECT t1.t, MAX(t2.v) AS max_v
FROM table_name AS t1
JOIN table_name AS t2 ON t2.t BETWEEN t1.t - 2 AND t1.t + 2
GROUP BY t1.t
If you use MySQL 8.x I think you should be able to do it using window functions, but I don't know the proper syntax for this.
In MySql 8 you can use a MAX OVER with rows between a range.
select t
, max(v) over (order by t rows
between 2 preceding and 2 following) v
from table_name

Extracting rows with a consecutive pattern that exceeds a threshold

I currently have this set of data.
Id
pattern
1
1
2
2
3
1
4
2
5
3
6
4
7
1
8
2
9
1
10
2
11
3
I have ids sorted ascending, and a column called pattern. The goal is to retrieve only the rows with a consecutive pattern >=3 down the table.
So the result would be:
Id
pattern
3
1
4
2
5
3
6
4
9
1
10
2
11
3
Since the pattern for Ids 3-6 have consecutively reached >=3, we will return these 4 rows.
Same goes for Ids 9-11.
Id 1-2 did not reach the threshold of 3. Same for Id 7-8.
Would appreciate any help!
Use SUM() window function to create the groups of the sequences and with MAX() window function check the max pattern in each group:
SELECT Id, pattern
FROM (
SELECT *, MAX(pattern) OVER (PARTITION BY grp) max_pattern
FROM (
SELECT *, SUM(pattern = 1) OVER (ORDER BY Id) grp
FROM tablename
) t
) t
WHERE max_pattern >= 3;
Or, with a correlated subquery, for versions of MySql that do not support window functions:
SELECT t1.*
FROM tablename t1
WHERE (SELECT t2.pattern FROM tablename t2 WHERE t2.Id = t1.Id + (3 - t1.pattern)) = 3;
See the demo.

Create histogram given start and end values in SQL

I have an SQL table with "start" and "end" columns: for the sake of simplicity, let's assume they are integers between 1 and 10. I would like to somehow obtain a histogram of the values between "start" and "end".
For instance, given the following rows:
start
end
3
8
4
9
I would like to obtain the following histogram:
time
count
1
0
2
0
3
1
4
2
5
2
6
2
7
2
8
2
9
1
10
0
I really have no idea where to start looking in the SQL syntax to get that result -- maybe an inner join?
You can use a recursive CTE to generate times -- if you don't have a handy tally or numbers table. Then join and aggregate:
with recursive cte as (
select 1 as t
union all
select t + 1
from cte
where t < 10
)
select cte.t,
(select count(*)
from t
where cte.t between t.start and t.end
) as cnt
from cte;
Here is a db<>fiddle.

Previous records in mysql

id game_id user_id user_playing_status user_turn_status
1 1 2 1 1
2 1 4 1 0
3 1 6 1 0
How can we access previous record of current record ?
If there are three records r1,r2,r3 in table
so previous record of r2 should be r1 , r3 should be r1 and r1 should be r3.
I use the following query
select user_id
from current_playing_users
where id < (select id from current_playing_users where user_id = 2)
But i am not getting previous record of first record.I want to get records in anticlockwise manner. Like in image previous user_id of 2 should be 6
Are looking you for the correlated subquery ? :
select cu.*.
(select cu1.user_id
from current_playing_users cu1
where cu1.id < cu.id
order by cu1.id desc
limit 1
) as prev_user_id
from current_playing_users cu;
you could use LAG function
select LAG(user_id) over (order by {your desired order}) as previous_row
from ..
LAG function return the former cell at the desired column with a pre-defined order.

Identify consecutive rows

I have a table in the following format:
cId seq
--- ---
A 1
A 2
A 4
A 5
B 8
B 9
A 12
A 13
I would like to write a query that would produce another table that looks like:
cId seq consecutive
--- --- -----------
A 1 1
A 2 1
A 4 2
A 5 2
B 8 3
B 9 3
A 12 4
A 13 4
What I am trying to do is identify consecutive seq values that have the same cId and then number them.
I was thinking of using Lag function to determine the previous seq value and then setting the consecutive column but don't know how to increment the value when I encounter the next break.
SELECT [cId],
[Seq],
CASE WHEN [Seq] - 1 = LAG([Seq], 1, [Seq]) OVER ( ORDER BY [Seq]) THEN 1
ELSE 2 END as consecutive
FROM #ConsecutiveData
This query will put a 2 next to the start of each sequence. That's the closest I have come.
I think author is not using MySQL, since, as far as I know, there is no LAG function in MySQL.
Below is a possible solution for MSSQL:
SELECT
cid,
seq,
DENSE_RANK() OVER (ORDER BY seq - row_num) consecutive
FROM (
SELECT
cid,
seq,
ROW_NUMBER() OVER (ORDER BY seq) row_num
FROM
test_table
) data
;
Check at SQLFiddle: SQLFiddle Example