How to add random interval to timestamp in MySQL? - mysql

We got the following table mytable:
+----+------------+------------+
| id | created | expired |
+----+------------+------------+
| 1 | 1496476314 | NULL |
| 6 | 1496477511 | NULL |
| 7 | 1496477518 | NULL |
| 12 | 1496477534 | NULL |
| 13 | 1496477536 | NULL |
| 15 | 1496477541 | NULL |
| 21 | 1496477548 | NULL |
| 22 | 1496477550 | NULL |
| 26 | 1496477565 | NULL |
| 28 | 1496477566 | NULL |
| 29 | 1496477583 | NULL |
+----+------------+------------+
We'd like to do the following:
set expired = created + random(15 - 30 minutes) as unix_timestamp where expired is null;
I currently have no idea to done it.
If u just can give me some ideas it would save my day.
I tried to convert the created timestamp to date_time and add to that date_time the wanted 15 - 30 minutes and finally convert the new_date_time back to unix_timestamp, but there should be an easier way.

If you want to add a random number of minutes between, say, 14 and 33, you can do it like this:
SET expired = DATE_ADD(created, INTERVAL 14 + RAND()*(33-14) MINUTE);
If you want to have seconds granularity, you need to add SECOND-typed intervals:
SET expired = DATE_ADD(created, INTERVAL 14*60 + RAND()*(33-14)*60 SECOND);
This would saves one datetime conversion if you had a DATETIME for the expired column, which makes it slightly easier to expire records (WHERE expired < NOW()). If you have an integer holding a Unix timestamp, then Darshan's answer is definitely the way to go, and you'd do well to calculate the Unix timestamp in your app and then plug it in the query:
WHERE expired <= 123456789
Having an index on that column would make expirations go blazingly fast. I think it might be even faster than the datetime method, but it's just a sensation, I haven't actually checked.

unix_timestamp is number of seconds elapsed since 1st January 1970. Now, if you want to add 15 to 30 minutes then the equivalent seconds would be 900 to 1800. Here's what you can do:
set expired = created + ROUND((RAND() * (900))+900) where expired is null;
This is how it works:
RAND() will generate a random number between 0 and 1
By using RAND() * (maximum - minimum)) + minimum we make sure we generate a number between 900 and 1800.
ROUND then rounds that number to nearest int.

Related

Check free time beetween times and dates with sql

Assuming that I have a table like this:
+----+----------------+------------+------------+-----------+----------+
| id | time_needed | date_start | date_stop | hour_start| hour_stop |
+----+----------------+------------+------------+-----------+----------+
| 1 | 30 | 2018-08-06 | 2018-08-06 | 08:00:00 | 08:30:00 |
| 2 | 96 | 2018-08-06 | 2018-08-06 | 10:45:00 | 14:21:00 |
| 3 | 20 | NULL | NULL | NULL | NULL |
| 4 | 56 | NULL | NULL | NULL | NULL |
+----+----------------+------------+------------+-----------+----------+
I know when I'll execute the operations 1 and 2, But instead for the 3 and 4 I just know the the time spent to execute the operations (20 and 56 minutes)
How can I check with mysql when I can execute the operation 3? I mean, is there a possibility to check when I have free time and for how long?
Looking at the table I can say that I have free time from the 08:31 to 10:44, but there is a way to check it with mysql?
EDIT
I would like to see the time free, beetween 8 am and 18 pm.
What you are demanding is not (all alone) a task of mysql. mysql can give you the DATA according to your query - but your programming language should add the logic of scheduling entries, whenever possible.
At first i would start with the following database changes:
Combine the date / hour columns into a datetime column.
remove the end_date / end_hour - you always can calcluate this with date_start + time_needed
So, you end up with a datatable like this:
+----+----------------+---------------------+
| id | time_needed | date_start |
+----+----------------+---------------------+
| 1 | 30 | 2018-08-06 08:00:00 |
| 2 | 96 | 2018-08-06 14:21:00 |
+----+----------------+---------------------+
Now, all you need to do is: Join the table with itself, and make sure everything is calculated as it should be:
-- new Task takes 25 Minutes.
SELECT DISTINCT L.* FROM time_table L LEFT JOIN time_table R
-- compare with every later schedule
on L.date_start < R.date_start
WHERE
-- use only rows that have enough time for the task that should be scheduled
(date_add(L.date_start, INTERVAL L.time_needed + 25 MINUTE ) < R.date_start
-- and only in the future
and date_add(L.date_start, INTERVAL L.time_needed MINUTE) > NOW()
-- due to the join, it might happen that we ignore entries in between.
-- make sure, there is no other task in the calculated timespan!
and not exists
(SELECT id FROM time_table x WHERE
x.date_start > L.date_start AND
x.date_Start < date_add(L.date_start, INTERVAL L.time_needed + 25 MINUTE) )
)
-- and ofc. the last row in the schedule.
OR isnull (R.date_start);
This returns both datarows, as 25 minutes can be scheduled right after every other task.
http://sqlfiddle.com/#!9/02020d8/1
14:21 - 08:00 is 6:21, and 30 minutes are "booked". So the gap is 5:51 - so a 350 Minute Task should fit after 08:00 - a 351 Minute Task not:
350 minutes to be scheduled:
http://sqlfiddle.com/#!9/02020d8/2
351 minutes to be scheduled:
http://sqlfiddle.com/#!9/02020d8/3
All you got to do afterwards:
Take the smalles id, and insert your schedule right after it. Remember, date_start will be prior_date_start + prior_time_needed.
See this example as well: Scheduling a 20 minute Task would have 3 options with the example data (Added 2 columns for your convenience):
http://sqlfiddle.com/#!9/02020d8/8

How to get the expired candidates in MySQL

I am having a table with the columns for expired_date and registered_date.
Expired date have set for 2 days to registered date.
Its look like this:
+--------------+--------------+---------------------+
| candidate_id | date_expires | date_added |
+--------------+--------------+---------------------+
| 1 | 2016-03-26 | 2016-03-24 14:42:18 |
| 2 | 2016-03-23 | 2016-03-21 15:43:40 |
| 3 | 2016-02-15 | 2016-02-13 14:53:30 |
| 4 | 2016-02-22 | 2016-02-20 14:54:19 |
+--------------+--------------+---------------------+
My question is, I want to select expired profile to current date and time.
This is how I tried it, but it doesn't work.
SELECT * FROM candidates WHERE date_added = DATE_ADD(date_added, INTERVAL 2 DAY);
Hope somebody may help me out.
Thank you.
You may try any of the following query which meets your need.
SELECT
*
FROM candidates
WHERE date_expires < CURDATE();
Or if you want to get the expired accounts with respect to date_added field then follow the query given below:
SELECT
*
FROM candidates
WHERE DATE_ADD(date_added, INTERVAL 2 DAY) < CURDATE();
EDIT:
For fine-grained comparison you may use the following query:
SELECT
*
FROM candidates
WHERE TIMESTAMPADD(DAY,2,date_added) < NOW();
Note: Actually you don't need to store the expired dates in database. Rather you can store the profile life time (in this case it is 2 Days) in database if this profile life time varies across different accounts. You don't need to store this in database if it's constant in nature (i.e. Always 2 DAYS).
So if you want to bring this change in your table structure then it would look like below:
+--------------+--------------+---------------------+
| candidate_id | days | date_added |
+--------------+--------------+---------------------+
| 1 | 2 | 2016-03-24 14:42:18 |
| 2 | 5 | 2016-03-21 15:43:40 |
| 3 | 3 | 2016-02-13 14:53:30 |
| 4 | 10 | 2016-02-20 14:54:19 |
+--------------+--------------+---------------------+
You need a modified query for this change.
Here it is:
SELECT
*
FROM candidates
WHERE TIMESTAMPADD(DAY,days,date_added) < NOW();
You're looking for this
SELECT *
FROM candidates
WHERE date_expires < NOW();

MySQL query date with offset given

In MySQL I have a table node_weather:
mysql> desc node_weather;
+--------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+-------------------+-----------------------------+
| W_id | mediumint(9) | NO | PRI | NULL | auto_increment |
| temperature | int(10) | YES | | NULL | |
| humidity | int(10) | YES | | NULL | |
| time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
Now what I need to do is the following: for every two hours of the current day (00:00:00, 02:00:00, ..., 24:00:00) I want to get a temperature. Normally the query could be like that:
mysql> SELECT temperature
-> FROM node_weather
-> WHERE date(time) = DATE(NOW())
-> AND TIME(time) IN ('00:00:00','02:00:00','04:00:00','06:00:00','08:00:00','10:00:00','12:00:00','14:00:00','16:00:00','18:00:00','20:00:00','22:00:00','24:00:00');
In the ideal case, I should get a result as 12 rows selected and everything would be fine. But there are two problems with it:
The table does not include the data for thw whole day, so for example the temperature for the time '24:00:00' is missing. In this case, I would like to return NULL.
The table sometimes record the data with the timestamp like '10:00:02' or '09:59:58', but not '10:00:00'. To resolve this case, I would like to add the offset to all the values in IN expression (something like that ('10:00:00' - offset, '10:00:00' + offset)) and it would select always just ONE value (no matter which one) from this range.
I know it is kind of awkard, but that is how my boss wants it. Thanks for help!
Okay, a bit more precise than what I wrote in comments:
EDIT: Had a bug. Hopefully this doesn't.
SELECT
time,
deviation,
hour,
temperature
FROM (
SELECT
time,
ROUND(HOUR(time) / 2) * 2 AS hour,
IF(HOUR(time) % 2,
3600 - MINUTE(time) * 60 - SECOND(time),
MINUTE(time) * 60 + SECOND(time)
) AS deviation,
temperature
FROM node_weather
WHERE DATE(time) = DATE(NOW())
ORDER BY deviation ASC
) t
GROUP BY hour
ORDER BY
hour ASC
Basically, group on intervals like 09:00:00 - 10:59:59 (by rounding hour/2), then sort ascending by those intervals, and within the interval by the distance to the center of the interval (so we choose 10:00:00 over 09:00:00 or 10:59:59).

MySQL select Current_timestamp between

I have a list of users in MySQL and on subscription the timestamp is set in the data base using the CURRENT_TIMESTAMP.
Now I want to do a select from this table where the subscribe date is between day X and day Y
I tried several queries but somehow they all turn up empty.
Here is my last version
SELECT *
FROM users
WHERE subscribe_date BETWEEN '2013-10-07'AND '2013-13-10'
As I know for sure this date: 2013-10-08 14:38:49
is in the subscribe_data field It should turn up somehow
What is the best way to do this?
Maybe good to know my 'subscribe_date' column has type 'timestamp' and is auto filled with 'CURRENT_TIMESTAMP'
Here is the data in this table:
+----+-----------+---------------------+
| id | firstname | subscribe_date |
+----+-----------+---------------------+
| 20 | Peter | 2013-10-01 14:37:17 |
| 21 | Jack | 2013-10-08 14:38:49 |
| 22 | Andrew | 2013-10-10 14:41:03 |
| 23 | Margret | 2013-10-14 14:42:46 |
+----+-----------+---------------------+
Since TIMESTAMP is up to seconds precision usually, you have to add time part:
SELECT *
FROM users
WHERE (subscribe_date BETWEEN '2013-10-07 00:00:00' AND '2013-12-10 23:59:59')
I've fixed your '2013-13-10' to '2013-12-10 23:59:59' since there's no 13-th month (and in DATETIME format it's YYYY-MM-DD, so month goes second)

mysql datetime range select

I have a recurring payment mode in the system. All is well, API successful response is logged on the database.
The concern of my question is, I'm about to automate the subsequent payment action (which unfortunately, the payment gateway doesn't support) of the system.
Via cron I'll schedule a check on whether which accounts must be included in the subsequent process and notice.
I have here a snip of the database entry:
+---------------------+---------------------+--------------------+
| payment_date | payment_expirydate | transaction_number |
+---------------------+---------------------+--------------------+
| 2012-02-14 03:47:15 | 2012-05-14 03:47:15 | 1-67815163 |
| 2012-02-16 00:53:03 | 2012-05-16 00:53:03 | 1-69010235 |
| 2012-02-16 08:57:16 | 2012-05-16 08:57:16 | 1-69027483 |
| 2012-02-16 09:08:06 | 2012-05-16 09:08:06 | 1-69027694 |
| 2012-02-16 09:58:17 | 2012-05-16 09:58:17 | 1-69028921 |
| 2012-02-17 09:28:32 | 2012-05-17 09:28:32 | 1-69072076 |
| 2012-02-17 06:17:45 | 2012-05-17 06:17:45 | 1-69068200 |
| 2012-02-17 11:12:08 | 2012-05-17 11:12:08 | 1-69074788 |
+---------------------+---------------------+--------------------+
I am having a difficulty in creating the SQL query for this. Assuming, the date today is 2012-05-16 and the time is 07:00:00. I want to get all the accounts which is today and less than the current time. For instance, the only valid account (based on the current date and time I indicated) I need is account 1-69010235.
Also, any tips if on what interval should I set my cron to run?
This query will return all records that expire today -
SELECT *
FROM accounts
WHERE payment_expirydate BETWEEN CURRENT_DATE AND (CURRENT_DATE + INTERVAL 1 DAY - INTERVAL 1 SECOND)
If you want all accounts expiring today but less than current time -
SELECT *
FROM accounts
WHERE payment_expirydate BETWEEN CURRENT_DATE AND CURRENT_TIMESTAMP
For codeigniter's AR implementation you should be able to use -
$this->db->where('payment_expirydate BETWEEN CURRENT_DATE AND CURRENT_TIMESTAMP', NULL, FALSE);
SELECT group_concat(transaction_number) as transaction_number
FROM tab
WHERE payment_date BETWEEN CURRENT_DATE AND CURRENT_TIMESTAMP
You can use this to return a string and use perl to split the string and pass to curl.
sqlfiddle here.
If you want all the records in the table you show that are valid for the current time - and valid means that the payment_date is earlier than now and payment_expirydate is later than now, you can use:
SELECT transaction_number from `table`
WHERE payment_date > now()
AND payment_expirydate < now();
Does that get what you want?