Delete rows older than 30 minutes in MySQL - php

In my table mytable. I have a column named session_time (float) where I store the time in microseconds when the row was added (I use the PHP function microtime(true) to get a float). How can I delete all rows from my table mytable which are older than 20 minutes?
I already tried something like this:
DELETE FROM mytable WHERE session_time < DATE_SUB(NOW(), INTERVAL 1800 SECOND)
But this deletes all rows!

UPDATED...
Instead of using php microtime(true) , you should use MySQL function NOW(). Delete the old column, and make a new one :
ALTER TABLE your_table ADD session_time DATETIME NOT NULL DEFAULT NOW();
Now when you add a row, it's session_time will be set to the current time automatically, and you do not need to insert any value for session_time.
Now for deleting all rows older than 30 minutes, use :
DELETE FROM your_table WHERE TIMESTAMPDIFF(MINUTE,session_time,NOW()) > 30;

Try
DELETE FROM myTABLE WHERE session_time < (now() - interval 30 minute)
I didn't test it. I think it shoud work as well.

It sounds like you're comparing a microsecond value generated in PHP, to a timestamp value generated in mysql. There's a few things that could go wrong here, since you may not actually be comparing time to time but time to float, or your PHP app is using a different clock than your mysql.
Since you're doing the comparison in SQL, you should save the session_time value based on SQL too. This is a good place for a default value, e.g.:
mysql> create table mytable ( id int not null, session_time timestamp default now() );

PHP microtime() uses unix timestamp format, not the DATETIME format. If you are storing things like that, you could use PHP to fill the query or use MySQL's unix_timestamp() function.
For PHP, it would be as simple as:
$query = 'DELETE FROM mytable WHERE session_time < '.time() - 1800;
I would recommend just using the DATETIME format on session_time though, you should take advantage of MySQL’s storage types.

Related

How to datenow minus datetime MySQL with PHP in second

i want to minus purchase date with datenow. i have table named count_sec :
|user_id| purchasedate |second|
| 1 |2015-06-06 08:36:05| |
| 2 |2015-06-06 08:36:15| |
example time now is 2015-06-06 08:37:00
what is the code if i am want the code to update the second to:
|user_id| purchasedate |second|
| 1 |2015-06-06 08:36:05| 55 |
| 2 |2015-06-06 08:36:15| 45 |
thank you
EDIT
i have already create this php, but the code is not work, how to fix?
<?php
require 'database/db.php';
$selectprchsdate = $mysqli->query("SELECT purchasedate FROM count_sec");
$row = mysqli_fetch_assoc($selectprchsdate);
$date = date('Y-m-d H:i:s');
$result = $date - $row['purchasedate'];
$mysqli->query("UPDATE count_sec
SET second = '".$result."'");
?>
In PHP you can use
// get current date and time
$now = new DateTime();
// create DateTime object for purchase date
$purchaseDate = DateTime::createFromFormat('Y-m-d H:i:s', $row['purchasedate']);
// calculate seconds
$seconds = $now->getTimeStamp() - $purchaseDate->getTimeStamp();
But the SQL solution suits this question better.
Try with the SQL query:
SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(purchasedate) as second from countsec
or this:
SELECT TO_SECONDS(NOW()) - TO_SECONDS(purchasedate) as second from countsec;
From MySQL Date and Time Functions
I am not understanding why you need to store this in a column in the table. As soon as it's stored, the value is old, and it will need to be updated again. (Don't do this.) But setting that issue aside for a moment...
As to why your code isn't "working"... your UPDATE statement is updating every row in the table. You've previously fetched one row from the table, and then calculated one value, and then the UPDATE statement doesn't have a WHERE clause to identify which row(s) you want to update, so every row gets updated with the same value. That's a big part of why your code isn't working.
And, there's no need to run a SELECT statement before you run an UPDATE. If you want to update all rows in the table, you set the column to an expression that returns the number of seconds between the current date and time and the date and time stored in purchasedate column.
One convenient way to do that is to use the UNIX_TIMESTAMP function to convert each of the DATETIME values into an integer value (number of seconds), and subtract them. For example:
UPDATE count_sec
SET `second` = UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(purchasedate)
As an alternative, you could use the TIMESTAMPDIFF function for an equivalent result:
UPDATE count_sec
SET `second` = TIMESTAMPDIFF(SECOND,NOW(),purchasedate)
But back to the issue of why this is wrong. You do not want to store second column in the table.
When you run a SELECT statement to return a row from the table, the value in this column is going to old.
Instead, you could just return a calculated value, calculated as of the time the SELECT statement runs, by including one of those expressions in the SELECT list. For example:
SELECT user_id
, purchasedate
, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(purchasedate) AS `calc_second`
, `second` AS `old_stored_value`
FROM count_sec
ORDER BY user_id
The point I'm trying to emphasize here... do not store the second value in the table. You'll be chasing it, and continuously updating every row in table, whether that's every five minutes or every five seconds. And the stored value is always going to be "old".
Why do you need that? If you want to find out which rows in the table have second between 60 and 120, for example, if you intend to run this query:
SELECT user_id
FROM count_sec
WHERE second > 120
AND second <= 60
You could just as easily rewrite that based on purchasedate
SELECT user_id
FROM count_sec
WHERE purchasedate > NOW() - INTERVAL 120 SECOND
AND purchasedate <= NOW() - INTERVAL 60 SECOND
And, you won't be "chasing" continuous updates of the rows in the table, generating rollbackup, recording changes in the InnoDB log, writing the UPDATE statements in the binary logs. If you are running replication slaves, those statements have to be read from the log and re-executed on the slaves. All in all, storing second is just a poor design choice.
You can use TIMESTAMPDIFF() function like below. See Documentation
SELECT TIMESTAMPDIFF(SECOND, NOW(), purchasedate)
from count_sec;
(OR) if you want to UPDATE
UPDATE count_sec SET `second` = TIMESTAMPDIFF(SECOND, NOW(), purchasedate);
Per your comment, if you want to delay for 5 minutes then either you can use
SLEEP(seconds) function
(OR)
Wrap your updation code in a stored procedure and run that in every 5 minutes (probably using some scheduler job)

Will specifying a SUBTIME interval in MYSQL prevent the query from unnecessarily going through the entire table?

Please tell me, if I specify an interval like such: subtime(now(), INTERVAL 1 day) inside a MySQL SELECT query while having a proper datetime column to use as reference - will this prevent from the query to look through the entire table (over 100,000 records in my case) each time it runs but rather look through records made only the past 24 hours? Is DESC order needed for the datetime table or such? Also, if I have SUM(column) in the query, will it also run only for the interval specified?
Edit: If I just would like to use the above mentioned SUM to sum a column where there only are integers of value "1" - would it be better to simply check how many rows the SELECT query returns with mysql_num_rows - is it more efficient in combination with the time interval setting?
Thank you!
It will in fact prevent MySQL to go through the whole table but not if you just subtime() in the SELECT-part. Instead you have to do something like this:
SELECT * FROM myTable
WHERE myDateCol BETWEEN DATE_SUB(now(), INTERVAL 1 day) AND now()
The query will now select only rows one day old. Add a B-TREE index on myDateCol to speed things up:
ALTER TABLE myTable ADD INDEX myIdx USING BTREE (myDateCol)
See MySQL doc on that topic

is there any possible way to store current time only via phpmyadmin in mysql

I want to store current time (for example 00:30) in one of my column , the default CURRENT_TIMESTAMP gives both date and time which i dont want.
or is there any way of retrieving only time from CURRENT_TIMESTAMP ??
You can use MySQL's built-in TIME() function to extract the time part of a datetime expression. For example:
mysql> select time(now());
+-------------+
| time(now()) |
+-------------+
| 18:21:38 |
+-------------+
1 row in set (0.03 sec)
Since CURRENT_TIMESTAMP is a synonym for NOW(), you can just use TIME(CURRENT_TIMESTAMP).
Try combining TIME() and NOW():
SELECT TIME(NOW());
Output: 15:20:31
Of course, your column will need to be of type "TIME".
When you create the table set the column type to TIME
If I understand your question correctly, I think you have a timestamp column that has a default value of CURRENT_TIMESTAMP:
CREATE TABLE yourTable (
...,
...,
currentTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
If you just want to store the current time, and not the date part, you could use a TIME column and trigger, that will insert the time part automatically:
CREATE TABLE tableName (
...,
...,
currentTime TIME
);
CREATE TRIGGER currentTime BEFORE INSERT ON tableName
FOR EACH ROW
SET new.currentTime = TIME(NOW());
(an example is here) and you might also want to use an UPDATE trigger. Or you can just use CURRENT_TIMESTAMP, and get only the time part with TIME function:
SELECT TIME(yourTimestampColumn)
FROM yourTable

MySQL default date() + 14 days, for a column?

I was wondering if the following is possible to do through MySQL or will it have to be done using PHP.
Task - "Expiry Date"
User enters product name
User clicks submit form button
Data is POST'ed and then sent to MySQL
Expiry date = date now + 14 days
What I am trying to achieve is a way for mysql to insert an "expiry_date" in a table column that will equal 14 days after the date the row was created in that table.
e.g.
product_name - foo
entry_date - 2012-02-01
expiry_date - 2012-02-15
I have a feeling it may not be possible to do in mysql unless using a stored procedure.
I am happy to do it in PHP however I was hoping if I could do it with mysql it would leave less scope for error in my system.
Thanks
Create a table and set up a trigger for that table.
CREATE TABLE product(
product_id INT PRIMARY KEY,
product VARCHAR(40),
entryDate DATETIME,
expDate DATETIME
);
CREATE TRIGGER test_trigger BEFORE INSERT ON `product`
FOR EACH ROW SET
NEW.entryDate = IFNULL(NEW.entryDate, NOW()),
NEW.expDate = TIMESTAMPADD(DAY, 14, NEW.entryDate);
On each insert into the table, the trigger sets the entryDate to the current time and expDate to 14 days time.
You can use this by using DateTime methods in MySQL:
DATE_ADD(date_starts,INTERVAL 14 DAY)
for example:
UPDATE events SET date_starts = DATE_ADD(date_starts,INTERVAL 14 DAY) WHERE event_id = 3;
For more details go here.
you can try this this function
DATE_ADD(now(), INTERVAL 14 DAY);
date = DATE_ADD(NOW(), INTERVAL 14 DAY)
or as said, alter your table structure for that field (attribute for that field=) to "on Update CURRENT_TIMESTAMP"
According to this source you can't use expressions as a default specifier.
So not sure if it has changed since the bug was posted.
I'm not sure however why I assumed that the OP wants to define it as a default value.
I believe MySQL won't allow you to use expressions in the default value. You might want to write a trigger.
MySQL does provide a TIMESTAMP datatype which can be set to CURRENT_TIMESTAMP when a row is created or updated. You might find this feature somewhat useful:
CREATE TABLE table1 (
`Column1` VARCHAR(50) NULL,
`Created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
)
Once you're sure that MySQL is filling that column as expected, you can write queries like this:
SELECT `Created`, `Created` + INTERVAL 14 DAY AS `expiry_date`
FROM table1
The easiest way to solve that is just insert the value you want - without trigger or later update, eg.
INSERT INTO <your_table> (name, expiry_date) VALUES ('foo', DATE_ADD(CURRENT_TIMESTAMP,INTERVAL 7 DAY))
I like this format better:
SELECT NOW()+INTERVAL 14 DAY

PHP mysql adding to a timestamp

I'm working in PHP with a MySQL db and I have a current timestamp field which is created when the field is made, I then have another field which (when a page is hit) I would like a SQL statement to insert a replica of the timestamp - only 2 days ahead. Any ideas on how I would go about doing this?
So you have a table like:
id
current TIMESTAMP DEFAULT CURRENT..
another TIMESTAMP
?
You can do something like
UPDATE MyTable SET another = ADDDATE(current, INTERVAL 2 DAY) WHERE id = :myId
MySQL Date and Time functions
How about INSERT [...] (... , ADDTIME(NOW(),'2 00:00:00' , ...)

Categories