How to get X hours after specific hour in mysql? - mysql

For example, given 1339372800, which is Mon, 11 Jun 2012 00:00:00 GMT, I would like to get the next X hours including 1339372800. So for the next 3 hours, the result would be
+------------+
| hours |
+------------+
| 1339372800 |
| 1339376400 |
| 1339380000 |
+------------+
I think I need to create a loop but I don't know how to proceed from that. Thanks.

You could use a numbers table as Creating a "Numbers Table" in mysql that contains all hours for a considerate amount of time, and query that:
SELECT hour
FROM hours
WHERE hour >= 1339372800
ORDER BY hour ASC
LIMIT 3
That makes the query really easy, and the table should not be too big, either. (Less than 90k rows for 10 years.)

Try:
SELECT *
FROM table
WHERE
hours between 1339372800 and DATE_SUB(1339372800, INTERVAL 3 HOUR)

Related

Storing a duration in mysql

I need to store durations such as the following in mysql:
- 30 seconds
- 20 minutes, 12 seconds
- 1 month
What would be the best way to store this, as the definition of a month can't be reduced, for example, to a number of seconds. My first thought was to store each increment separate, for example:
- num_seconds
- num_minutes
- num_hours
- num_days
- num_months
This could store the above, but I was hoping there was a more direct and less verbose way of doing this.
My first option would be to store duration as a number of seconds with datatype INT. This will make computation and comparison operations fast and clean. Also you can easily compute the duration between two datetime values, by substracting their Unix timestamp. When you need to display the values, you can use mysql sec_to_time function :
However if you are looking to manipulate big durations (months, years), this will not work. In that case I would fallback on a VARCHAR column with iso8601 duration format, like P3Y6M4DT12H30M5S for 3 years, 6 months, 4 days, 12 hours, 30 minutes and 5 seconds. It is a well known format that is supported by many applications (but will be more tedious to manipulate).
Store your intervals for years to months as an integer counting the number of months (12 months = 1 year) and your intervals for days to seconds as an integer of number of seconds.
You can then use the DATE_ADD function to figure out your dates. Here's a SQL Fiddle example showing storing intervals as months and seconds, and adding them to a fixed date:
MySQL 5.6 Schema Setup:
create table mytab (dt date);
insert into mytab values (date '2018-01-01');
create table intervals (months int, seconds int);
insert into intervals values (13, 3661), (-13, -3661);
Query 1:
select dt
, months
, seconds
, date_add(date_add(dt, interval months month)
, interval seconds second) result
from mytab cross join intervals
Results:
| dt | months | seconds | result |
|------------|--------|---------|----------------------|
| 2018-01-01 | 13 | 3661 | 2019-02-01T01:01:01Z |
| 2018-01-01 | -13 | -3661 | 2016-11-30T22:58:59Z |

Intersect between two date intervals

I need to find intersect between to date intervals for example
I have one date
2015-01-01 and 2015-03-01
and second value
2015-01-01 and 2015-01-15
I wanna get results 15. So how many days of second date is included in first date range?
Any ideas how to do it with MySql?
In MySQL you can use the following SQL statement to get what you need:
SELECT DATEDIFF(LEAST('2015-03-01 23:59:59','2015-01-15 23:59:59'),GREATEST('2015-01-01 00:00:00','2015-01-01 00:00:00'))+1 AS days;
+------+
| days |
+------+
| 15 |
+------+
This will get the date difference in days using DATEDIFF
You can use CASE for condition like below:
SELECT (CASE
WHEN '2015-01-01'>= '2015-01-01' AND '2015-04-15'<='2015-03-01'
THEN DATEDIFF('2015-01-15','2015-01-01')+1
ELSE 'out of range'
END) AS days;
You can specify your own else condition and date range.

MySQL store time conditions

I am currently working on a platform where I would like to offer some rentals.
I want to store all possible rental types in the database, so I do not need to take care of logic in code.
Basically I want to offer following rental-times:
1 day
7 days
5 days / need to be weekdays ( which is monday to
friday )
2 days / weekend ( needs to be saturday till sunday )
1 month / which will be from e.g. 14 of some month till 13th of following month
For the time of days I thought of storing data in minutes, this is easy to figure out.
If there is a weekday condition I thought of using the DAYOFWEEK Indexes, so I could define for 5 days, the first day of rental needs to have index 2 which is Monday, for weekend I could define that the day of rental needs to have index 6, which is Saturday.
rental_type_id | rental_time_in_minutes | rental_label | rental_start_day_indexes
1 day would be like
1 | 1440 | 1 day | 1,2,3,4,5,6,7
7 days
2 | 10080 | 7 days | 1,2,3,4,5,6,7
5 days
3 | 7200 | Weekdays | 2,3,4,5,6
etc.
Is this a way to go for, or should I store the rental time just in days?
Any help, advice, critics or cheers are helpful!
Thanks.
Depending on how you use this, storing rental time in minutes could cause issues around DST where you have 23 or 25 hours in a day.
Also storing the indices as comma-separated lists will cause you problems. I would make a mapping table. That column is not in normal form and will be tough to query.
I would honestly just make different tables for the different durations.
I would store the durations in seconds. Because it makes the whole thing easier to query and more felxible. Lets say you have those rental durations. Table durations:
d_id type duration
1 1 day 01
2 3 days 03
3 7 days 07
I would suggest that you use normal timestamps for the rentals. I would store the start and end timestamp. Lets say you have the following table.
In this example I'm using days instead of a timestamp just to make it easier to show. Let's say today is day 3. Table rentals:
customer start end
Bob 02 05
Joe 10 11
Ian 03 04
Let's say you want to want to get all the currently active rentals (Bob & Ian). You can fetch it like this:
SELECT * FROM `rentals` WHERE `start`<3 AND 3<`end`
You can find all which of rental type "1 day" (Ian) by using this query:
SELECT * FROM `rentals`,`durations` WHERE `end`-`start`=`duration` and `d_id`=1
The advantage of using timestamps is that you can very precisely set the rental start and end time. You can check how many hours and minutes the customer is too late with giving the object back. Then you can easily calculate the exact additional fees.

Get peak amount of active rows from all time

I have the following problem. I have a mysql table that has a startdate and and enddate. Each row is considered active between those dates. Some rows are no longer active, but have been active in the past. For example the following table:
id start end
1 2014-11-11 00:00:00 2015-01-31 23:59:59
2 2014-09-25 10:16:14 2015-06-01 23:59:59
3 2013-12-24 00:00:00 2014-12-01 23:59:59
4 2014-08-13 00:00:00 2016-01-31 23:59:59
5 2013-09-11 00:00:00 2014-09-10 23:59:59
My actual table has way more data than that. Now I need to know what the peak amount of concurrent active rows is without knowing when that peak actually occured. How would I do this in SQL? In the example 4 rows are active at the same time (1-4, not 5) in the time between 2014-11-11 and 2015-01-31 23:59:59. The actual peak time doesn't matter to me as much as the peak amount itself.
Thanks for your help
Find different timestamps of interrest using UNION ALL, count number of active tasks at these timestamps:
select ts, (select count(*) from tablename t2
where timestamps.ts between t2.start and t2.end) as count
from (select start as ts
from tablename
union all
select end
from tablename) as timestamps
order by count desc
limit 1
Finally order descending and pick the highest value only!
(From a non MySQL user, so some details may be wrong... Please comment if that's the case and I'll edit!)

Generating a MySQL hourly breakdown from current timestamp

I'm afraid this is probably a very embarrassingly easy question - but my mind is just completely stuck at this hour.
I have a table that stores the number of activities carried out by different people, and the time it took place in.
I want to create a report that accepts the person's name as a parameter, and show the number of activities per hour for that person during each of the previous 24 hours starting from current timestamp (now()).
Right now,
SELECT hour(TimeStamp), activities FROM tbl1
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 24 HOUR) AND Name = ?
GROUP BY hour(timestamp)
only returns to me those hours when any activity was present. However, I want a complete 24 hour breakdown with zero for when there was no activity.
i.e. I'm getting
Hour | No. of Activities
1 | 34
4 | 22
9 | 86
but I want
Hour | No. of Activities
1 | 34
2 | 0
3 | 0
4 | 22
5 | 0
... etc.
How do I do this?
(The order of hours in the example is irrelevant)
You can create a hourly table, and do a LEFT JOIN
create table hourly
(
/* hour is not a reserved keyword */
hour smallint(2) not null default 0
);
insert into hourly values (0),(1).... until 24
SELECT
hourly.hour,
COALESCE(COUNT(activities),0) AS "No of Activities"
FROM hourly
LEFT JOIN tbl1 ON hourly.hour=hour(tbl1.TimeStamp)
WHERE
tbl1.timestamp>=DATE_SUB(NOW(), INTERVAL 24 HOUR) AND
tbl1.Name=?
GROUP BY hourly.hour
ORDER BY hourly.hour;