I would like to store a duration in database, in my case it's a training duration (sport). We set when we do the training (datetime) and how long the session is (duration).
At the moment, I've choose the Time type, then I've: 01:00:00 for an hour of training, and retrieve a Datetime object in PHP (but I think it's not ideal to sum them for exemple) and in my form I've an undesired behavior: the html time type automatically set the current hour when the time is empty.
I hesitate in:
keep time, it seem logical/simple to have something like: 00:00:00
store it as secondes or minutes as an integer, maybe simpler to do sum of training amount for exemple (need to create a converter to display it as 00:00 or 00:00:00, and find a nice way to fill it in form)
a way I've not think ?
Thanks a lot for your help.
The correct data type to store a duration is interval.
This makes it easy to do date arithmetic: you can simply add the duration to the start time to get the end time:
SELECT INTERVAL '01:30:00';
interval
----------
01:30:00
(1 row)
SELECT TIME '09:00:00' + INTERVAL '01:30:00';
?column?
----------
10:30:00
(1 row)
SELECT TIMESTAMP WITH TIME ZONE '2021-03-28 02:00:00+01' + INTERVAL '01:30:00';
?column?
------------------------
2021-03-28 04:30:00+02
(1 row)
I'm not sure what your question is. Postgres has no problem using sum() on the time data type:
select sum(t)
from (values ('03:12:00'::time), ('05:27:00'), ('18:59')) v(t)
You can also use interval.
You might have issues if individual durations exceed 24 hours. If that is a potential issue, just use hours, minutes, or seconds.
If you have a problem with "empty" values, then you will need to set them explicitly. It sounds like a bug on the HTML side.
Related
I have table in MySQL which has columns
id(primary key) ,deviceid(varchar) ,date(varchar),time(varchar),value(varchar) parameter(varchar)
I made mistake by separating time and date fields in my DB columns and then with my business logic where with lot of repetitive code
A new record is inserted every minute in database every day. My major query is to fetch data between two dates for a given number of deviceids such that data only one value is selected per interval ( this interval is decide by user input for exampe if interval is 1 hour i need 1 value between interval 00-01 hrs,1 value in terval hrs 01-02 hrs and so on 1 value from 23-24(00) hours )
My query is taking almost a minute to get data for and display for 2-3 days of data . And shorter the interval gets more time it takes .
I am new to databases and only knows basic CRUD operation . I have designed tabled through php myadmin default options.
I read about the concept of indexing to improve search performance and i am confused on which columns should I apply indexing.
Also my value columun is currently varchar but values of value column are all floating numbers(temperature/humidity of a boiler room). Can changing its type from varchar to int increase my speed ?
here is more explanation
I am using my php to display report
my time is in string format and so is date
for example date is stored as '08.31.2020'
and time is stored '23.05' (hours,min)
let say I want data from '08.01.2020' to '08.20.2020' and interval of 1 hour =60 minutes
Here is my business logic and querys
$time1 ='00.00'
$time2 ='01.00' // here I have increased time by adding 60 minutes to $time1 .
while(fromDate <= toDate)
{
for(each device in array)
{
$query = "Select parameter,value,time,date from currentdata where deviceid='device[$i]' and date='fromDate' and (time > '$time1' and time <= '$time2' ) order by time limit 1 "
}
$time1=$time2; //change interval
$time2 =$time2 +60 minutes //
If(time1>=time2)
{
// increment From date by 1
}
}
No of devices are about 30 -35 .
Parameter is just a name which will be either Temperate of humidity
Any general advice ,suggestion ,criticism will be helpful.
Use appropriate datatypes in the table. Numeric quantities should not be put in VARCHAR; use INT, DECIMAL, or FLOAT, as needed. (Or variants on them.)
If your incoming data is not "clean", the read it into a VARCHAR and 'cleanse' it as you copy it into the SMALLINT UNSIGNED, etc, in the real table.
Also DATE must have the year first.
Use things like + INTERVAL 1 HOUR for simple date or time arithmetic.
Usually it is better not to split date and time for storage, but to split as needed on output.
On your other Question, I admonished you to do the SELECT with a JOIN, not a loop.
After addressing all those things, provide SHOW CREATE TABLE, the new query, etc. Then I will weigh in on the index.
How should I store Birthdate's in MySQL so that I can easily update everyone's Age on a daily basis via a Cron Job?
Does it even make sense to store the Age AND the Birthdate so that when searches involving the Age are made, I don't have to calculate each Age on-the-fly and waste CPU resources?
If so, how should I 1) store the Birthdate, and 2) calculate the Age each day?
I can imagine the daily cron script first filtering out the user's whose Birthdate month is not the current month, then filtering out the user's whose Birthdate day is not the current day, and then incrementing by one the age of each user that is left.
Does this make sense? If so, how would I do that? Is there a better way to do all of this?
The simple answer is don't; never store a persons age. It changes for each person yearly but, as you say, you have to check that it's correct for every person daily.
Only store the date of birth, and then calculate the age when selecting from the database. It's only today - date of birth so takes almost no CPUs at all.
EDIT:
To expand upon my comment in ManseUK's answer there's also the possibility of failure. What happens if your server / database is down? Or your update fails to run at its specified time? Or someone comes along and runs it manually after the update already been run for that date? Or someone turns off your scheduler? There's no danger of this happening if you calculate Age as you select from the database.
To select where age is between 25 and 30 years and assuming a DATE column dateofbirth your query would be something like:
select *
from users
where dateofbirth between date_add( curdate(), interval -30 year )
and date_add( curdate(), interval -25 year )
Ensure users is indexed on dateofbirth.
No, don't store age, just calculate it in your queries. As for the birthday, I prefer to have all my date/time in unix timestamps (because I hate to deal with portability across date-format-changing locale settings)
Does it even make sense to store the Age
No.
I don't have to calculate each Age on-the-fly and waste CPU resources?
As a matter of fact, you'd waste a zillion more "CPU resources" (of which you have too vague idea to be concerned of) with your everyday update approach.
Is there a better way to do all of this?
Store the birthdate and calculate the age at select time
what if you want to find out all the ones whose Age is greater than 25 but less than 30?
this is quite trivial query like this
WHERE birth_date BETWEEN date_sub(curdate(), INTERVAL 25 YEAR)
AND date_sub(curdate(), INTERVAL 30 YEAR)
the query would using an index (if any) and thus be blazing fast, without any [unnecessary] denormalizations
Im going to go against the majority all of the answers here.
I would store both ...
updating the age is quick and simple - a single mysql query could run every day and its done
calculating the age is time consuming when you have lots of page views - amount of times its viewed far outweighs the number of changes
Just imagine a table scenario - a table with 100 or 1000 rows that shows the age of a person ... how long is that going to take to compute ???
I always thought that Stackoverflow calculated the Reputation dynamically but you can see on the Stackoverflow data explorer that they dont - see the User object in the schema on the right. Its recorded and updated each time its changed - I would guess that this is purely because of the amount of times its viewed far outweighs the number of changes
I don't think it's totally true that computing age dynamically takes a lot of memory.
Why not create a table CALENDAR with 365 rows 1 row for each day of an year. And store a list of userid against the day corresponding to their birthday.
For each day just refer the table entry for that day and refresh the age of only those selected users.
This will reduce the complexity greatly even when the user base increases.
Suppose I want to see the last 24 hours data from my database which is saved as a Unix Timestamp.
So, the process will be:
Get current time.
Get last 24 hours time.
Unix Timestamp ---
current time --- 1439212332
last 24 hours ---- 1439207714
I have tried in many different ways, but all my processes are wrong. Can someone tell me how to solve this problem ?
I am working on PHP and using a MySQL database.
Your query would look something like this:
SELECT * FROM table WHERE mycolumn < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 DAY))
This takes the date of 'now', subtracts one day from it and then converts it to a Unix timestamp to use on whichever column you're storing the value in.
Scenario
UDPATE
Please ignore the commented section. After thinking for an alternative, I came up with this:
Let's say I have
$date = '2012-10-03 13:00:00'
The time interval range is
2012-10-03 12:00:00 to 2012-10-03 14:00:00
Now $date falls between the time range mentioned above. Any ideas on how to compare a date time with a range of date time? I've come across functions which compare either just date or just time but not both at the same time. Any help much appreciated.
/*I'm building a school timetable and want to make sure that a room cannot be assigned to two different periods if it is already occupied. I have datetime values of **`2012-10-03 13:00:00`** (the start time of a period. Let's call it **abc** for reference) and **`2012-10-03 13:30:00`** (the end time of a period. Let's call it **xyz** for reference).
My database table contains columns for room number assigned for a period and the start and end time of that period. Something like this:
room_no | start_time | end_time
5 2012-10-03 13:00:00 2012-10-03 14:30:00
This means for October 3, 2012 room 5 is occupied between 1pm and 2:30pm. So the datetime values that I have (abc & xyz) will have to be assigned to a room other than 5.
I'm at a loss of ideas on how to go about validating this scenario, i.e. make sure that the period with time interval between abc & xyz cannot be assigned room number 5.
Any help would be appreciated. Thanks in advance
PS : I'm not asking for code. I'm looking for ideas on how to proceed with the issue at hand. Also, is there a way a query can be build to return a row if `abc` or `xyz` lie between `start_time` and `end_time` as that would be great and reduce a lot of workload. I could simply use the number of rows returned to validate (if greater than 0, then get the room number and exclude it from the result)*/
if(StartTime - BookingTime < 0 && BookingTime - EndTime < 0)
{
// Booking time is already taken
}
You can do this in SQL with TIMEDIFF().
I'm working on something similar and perhaps an easier way to code it would not be using times but timeslots? The way I thought of doing it was a table bookings (date, slot ids, room) table slots (with maybe slot ID and TIME) and per booking use a certain amount of slots.. then when you look for when the room is available it shows you per date what slots are free.. Just an idea.
Basically i think you need the first available room_no to be assigned to your abc-xyz timespan. So, you should be fetching the first good value that is not in the already-booked set.
Example query could be something like this
select room_no
from
bookings
where
room_no not in (
select
room_no
from bookings
where start_time >= 'abc' and end_time <='xyz'
)
limit 1
First, an entry in the database:
I have an input form that writes start date, start and end times (in hour and minute) of working days plus lunch break in minutes (in the example dato=date, modetime=start hour, modeminut=start minute, fyrtime=end hour, fyrminut=end minute). I need to do several calculations:
First calculate the date, start hour and minute into the datetime field modetid.
The do a similar calculation with the end hours and minutes, but move the date up one day if end hours is less than start hour (lets call it fyrtid)
And finally calculate the difference between fyrtid and modetid minus the pause minutes.
Can it be done directly and automatically in the database (if yes, how) or do I need some PHP to do it (and again, if yes, how)?
I know its a tall order but I have not been able to find much information on date/time calculations that made much sense on my low level of knowledge. Any link to a comprehensive guide on date/time calculation in MySQL or PHP would also be greatly welcomed.
I suggest you to work by php function time() it's based on unix timestamp ( like UNIX_TIMESTAMP() in Mysql ) unix time is like this : 1307387678.
Use a calender in your form for start time also for your end time.
put a facility what clients could select time of day ( hour and minutes ) then covert those fileds by strtotime() to unix timestamp like following code ( set date format to mm/dd/yyyy ) :
$startdate = strtotime ( "$_POST['calender_start'] $_POST['hour_start']:$_POST['minutes_start']" );
$enddate = strtotime ( "$_POST['calender_end'] $_POST['hour_end']:$_POST['minutes_end']" );
Change your db table fields to : cpr,startDate,endDate,pause,basked,.....
it's so flexible.
while you want to fetch special recorde you could fetch rows by this sql :
SELECT ...... FROM [TABLE_NAME] WHERE [VALUE] BETWEEN startDate AND endDate
I hope it be usefull for you