I got a system that pings to the database every 2 to 5 seconds, when an user is connected the application. Depending on his connection, the ping timeframe can be bigger, like 10 seconds or so.
Example:
Pings: 1,4,6,8,9,12,16,20,50,180,187,189,200,203,206,210 ...
I'm running a query to grab ranges that does not exceed 1 minute between the pings, group them, so I can tell for how long the user has been connected:
Here is the query I'm running to select the results, as advised by @fancyPants on this question: MySQL query to group results by date range?
select
userid, groupnum,
min(ping) as start_date,
max(ping) as end_date,
max(ping) - min(ping) as duration
from (
select
*,
@groupnum := if(@prevUser != userId, @groupnum + 1, @groupnum),
@groupnum := if(ping - @prevTS > 60, @groupnum + 1, @groupnum) as groupnum,
@prevUser := userid,
@prevTS := ping
from
Table1 t
, (select @groupnum:=1, @prevTS:=NULL, @prevUser:=NULL) vars
order by userid, ping
) sq
group by userid, groupnum
Producing the following results:
user: X | start_date: 1 | end_date: 50 | duration: 49
user: X | start_date: 180 | end_date: 210 | duration: 30
I need help, adding to this query, an statement that will do the following.
1st. Insert the selected rows into a new table with the excatly same schema the query returns:
id: auto_increment| user: X | start_date: 1 | end_date: 50 | duration: 49
id: auto_increment| user: X | start_date: 180 | end_date: 210 | duration: 30
2nd. Delete the selected rows, that were selected on the query and inserted into the new table.
This query will be run by a cronjob on the server, every 10 minutes. So I can clean the ping table, that will be heavily hit, and store into a new one the values that we are going to display to our surfers.
On the new query, I need a clause to filter non expired pings. Non expired pings, are the ones done no longer than 60 seconds before the current time when the cron runs. For example, if now = 100, the last ping to grab can not be less than 41. This way, when the cron runs, I don't select the rows from the users that are still pinging to the database.
Can it be done in one query, or will I need two?
Thanks,
(following up on my previous answer)
What exactly is stored in the ping_timestamp column? Unix timestamp or something else? I will assume it is unix timestamp.
Create the table that will hold the user activity data:
Aggregate the data skipping the intervals that are not closed yet:
After that we can delete the processed rows based on the data in the user_activity table:
Apart from that it's not possible to combine insert, delete and select statements, I wouldn't recommend it anyway.
Okay, step by step...
Here a "trick" comes in handy. Execute your query but write
This will automatically create a table (and inserts the data), but this usually has to get adjusted, as there are no primary keys or indexes created and the datatypes sometimes don't fit. Your query would produce something like this (maybe some things are different when you execute it, like the engine or the character set, those settings depend on the default settings):
(you can get the above by querying
SHOW CREATE TABLE ping;
)I suggest to always have a primary key in a table. It seems that
userid
andgroupnum
would be a good primary key. If you don't know you can also stick with an autoincrement column. Anyway, I'd adjust the table like this:Maybe you want to add an index on the other columns...
Now that you have your new create table statement drop the old table and recreate with above statement (or with your adjustments). I did so by adding the
DROP TABLE ...
statement above theCREATE
statement.Now you want to insert the data.
Next step...
I'm a little lost here. Which ones do you want to delete? The ones from the old table, right? Like in this sqlfiddle. But which ones exactly? The query from your questions just displays them as groups. Clear that up and write me comment, then I'll continue to answer...