Im trying to avoid multiple sql inserts in a database. The idea is to wait at least 5 minutes before inserting again.
Getting time from last insert using
$query ="SELECT fecha
FROM almacen
WHERE fecha > NOW() - INTERVAL 5 MINUTE
ORDER BY id DESC LIMIT 1"
$espera=mysqli_query($conexion, $query)
if (empty($espera)) { inserting code } else { close }
But the query returns nothing when it should be returning a value. I was thinking it might be a problem since date was inserted using php date ( "j/n/Y h:i");
Should i change the time format? what should i use?
If you wanted to restrict your rows to only 1 entry per 5 minutes I would:
Create a column called insert_interval DATE and create a unique index on that column. Then just attempt your insert, setting the value of insert_interval to
whatever 5 minute interval the insert time falls under.
E.G. Normalize date to 5 minute interval.
select now() - interval (mod(minute(now()),5)) minute - interval second(now()) second;
Insert
insert into table(columns ..., insert_interval) values(
..., now() - interval mod(minute(now()),5) minute - interval second(now())
);
Only 1 row is allowed per 5 minute interval starting on the hour. So 1 row from 00:00:00 - 00:04:59, and so on. Any attempt to insert another row in that time window, would result in a duplicate key error, that you can catch and take appropriate action.
SQL Fiddle
Uncomment the last insert to see the error on build schema.
Related
I have timestamps in a table order_onsite_interpreter column called assg_real_timestamp.
I need to get all rows where assg_real_timestamp is 10 minutes before assg_real_timestamp.
The logic is this: I get all rows that are 10 minutes before the session starts(session starts as shown with assg_real_timestamp) and then I send a push notification to the user on a ios app.
So if 10 minutes or less are before the session starts i have to fetch the rows.
This is an example, where I stop. I suspect I have made the wrong query.
SELECT *
WHERE scheduling_type IN ('get_call', 'conference_call')
AND push_notification_sent = 0 AND is_phone = 1
AND assg_real_timestamp <= now() - INTERVAL 10 MINUTE
This is how to get all rows with assg_real_timestamp with a value set in the past 10 minutes.
SELECT * FROM `<table_name>`
WHERE scheduling_type IN ('get_call', 'conference_call')
AND push_notification_sent = 0
AND is_phone = 1
AND assg_real_timestamp BETWEEN DATE_SUB(NOW() , INTERVAL 10 MINUTE) AND NOW()
Mysql: DATE_SUB()
See also: MySQL Select rows where timestamp column between now and 10 minutes ago
So if anyone has to retrieve all rows from the database, by looking at a columns timestamp that's in GMT, where the timestamp is less that 5 minutes from now()
SELECT orderID, scheduling_type, frm_lang, to_lang, customer_id, amount,
onsite_con_phone, assg_frm_date, assg_frm_st, timezone FROM
`order_onsite_interpreter` WHERE scheduling_type IN ('conference_call',
'get_call') AND push_notification_sent =0 AND is_phone =1 AND
DATE_SUB(CONVERT_TZ(DATE_FORMAT(FROM_UNIXTIME(assg_frm_timestamp), '%Y-%c-%d
%T:%f'), '-7:00', '-0:00'),INTERVAL 5 MINUTE) BETWEEN CONVERT_TZ(DATE_SUB(NOW(),
INTERVAL 5 MINUTE), '-7:00', '-0:00') AND CONVERT_TZ(NOW(), '-7:00', '-0:00')
-7:00 is where I need to convert from my server's timezones to GMT timezone. It's a matter of syncing my values to GMT and them i can compare the timestamp and now(). This works, like this:
A session starts at 02:03, meaning that in 02:03 - 00:05 = 01:58 the cron job that's fired every minute should retrieve the rows from order_onsite_interpreter table. After retrieving the row, I then send a push notification to user's app with message 'Your scheduled session is about start in 5 minutes, please login to the app'. And set push_notification_sent = 1 so the user doesn't receive the message anymore in the scope of the five minutes that the query from cron job finds.
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)
I want to insert data into a table on 1st day of every month. And it has to be just for one time. I mean one row for each 1st day of month. I am doing all this in a PHP file and using mySql.
So far i got this much-
if(Date('j')==1)
{
$query = select 1 from table where extract (year from t1) = extract(year from now()) and extract(month from t1) = extract(month from now()) LIMIT 1
if (#mysql_num_rows(mysql_query($query)) == 0)
{
//perform insert operation
}
}
I haven't tried this query till yet.
Maybe this will do the trick
SELECT * FROM xxx WHERE (DATE_FORMAT(CURDATE() ,'%d')==1)
SELECT DATEADD(mm, DATEDIFF(mm,0,GETDATE())-1,0) as StartOfLastMonth
SELECT DATEADD(mm, DATEDIFF(mm,0,GETDATE()),0) as StartOfThisMonth
SELECT DATEADD(mm, DATEDIFF(mm,0,GETDATE()),0) as StartOfNextMonth
Try out below event scheduler
CREATE EVENT myevent
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MONTH
DO
"YOUR QUERY"
Your have to run this on the date on which you want to run on 1 month interval.
You get more information on http://dev.mysql.com/doc/refman/5.1/ja/create-event.html
You have two solutions, depending on what you exactly want.
If your data must be inserted at the first day: the only way is to insert it using a cron job which run at the correct time. You can use the mysql scheduler to do the job if it's only mysql related.
If your data need to be in the table after the first day, but you don't care if it is added in realtime or only when you access that data then you don't need a cron job. You can check for that data when you access it, then insert it before reading if it's not already present.
you can achieve with mysql event scheduler--
http://dev.mysql.com/doc/refman/5.1/en/events.html
CREATE EVENT IF NOT EXISTS `my_old_data_cleaner_event`
ON SCHEDULE EVERY 23 DAY_HOUR
COMMENT 'Clean up Service Start at 11:00PM daily!'
DO DELETE FROM my_table WHERE created_date < (NOW() - INTERVAL 1 MONTH);
OR for Stored Procedure.
CREATE EVENT IF NOT EXISTS `my_old_data_cleaner_event`
ON SCHEDULE EVERY 23 DAY_HOUR
DO CALL my_sp_cleanup_old_data();
So I have a MySQL table that looks something like this:
id timestamp action timePassed
1 2012-07-10 22:44:00 start 0
2 2012-07-10 22:44:50 pause 50
3 2012-07-10 22:45:30 play 50
4 2012-07-10 22:47:25 pause 205
5 2012-07-10 22:48:05 play 205
I don't know how obvious it is but what's happening here is basically on every 'pause' row I am calculating the difference in seconds between the current timestamp and the timestamp of the 'start' row.
The only way I can think of doing this is to INSERT a new 'pause' row into the database so the timestamp is generated...then query the database for the timestamp of that 'pause' row...calculate the difference in seconds between that 'pause' row and the 'start' row using PHP...then UPDATE the 'pause' row with the timePassed result.
My question is whether or not there is a better way to do this (i.e. using timediff or some other MySQL command). The issue is the 'pause' timestamp doesn't exist until I make the INSERT, so I feel like that needs to happen first before I can make any calculation?
Well if your table is like this and your requirement is like this then you are on track..
However better if you check the second difference between last row and last to last row. This will give you idea for how many second user has PAUSED or Played the TRACK.
INSERT INTO table (timestamp, action, timePassed)
SELECT now(), 'pause', SECOND(timediff(now(), timestamp))
FROM table
WHERE ID = (Select Max(ID) from Table)
Put action as you like so you can insert time difference between two.
The only way I can think of doing this is to INSERT a new 'pause' row
into the database so the timestamp is generated...then query the
database for the timestamp of that 'pause' row...calculate the
difference in seconds between that 'pause' row and the 'start' row
using PHP...then UPDATE the 'pause' row with the timePassed result.
You can INSERT the already calculated row.
INSERT INTO table (timestamp, action, timePassed)
SELECT now(), 'pause', SECOND(timediff(now(), timestamp))
FROM table
WHERE action = 'start'; -- and/or other WHERE clauses.
This will introduce a skew in time due to the time needed to retrieve the 'start' row (but with index on action (and maybe timestamp if the row is very large), that time should be negligible).
I would recommend not storing timePassed explicitly at all, since by having each event's timestamp, you already have every interval stored once. If you separately store timePassed, you'll be storing the same data in multiple places. To quote E. F. Codd, "If something is true, saying it twice doesn't make it any more true." Also, you're subject to update anomalies when you store the same thing multiple times.
If you want to calculate the interval with a query, this might work.
SELECT event.id,
event.timestamp,
event.action,
TIME_TO_SEC(TIMEDIFF(event.timestamp, start_event.timestamp)) time_passed
FROM event
JOIN (SELECT timestamp
FROM event
WHERE event.action = 'start') start_event ON 1 = 1
Basically this query should select all the fields inserted in the last 30 minutes, but it doesnt, it selects absolutely every row making my script output wrong data
SELECT count(*) FROM mytable
WHERE `time` >= DATE_SUB(UTC_TIMESTAMP, INTERVAL 30 minute)
My time field stores the time in this kind of format 2011-06-08 22:32:03
The query works, but it selects every row, not the ones inserted in the last 30 minutes.
Try
SELECT count(*) FROM mytable
WHERE `time` >= DATE_SUB(NOW(), INTERVAL 30 minute)
Add parentheses to your query - UTC_TIMESTAMP() or use NOW() - quite simpler for me.