setting up a mysql database to record tasks - mysql

I am trying to setup a MySQL database using PHPMyAdmin. Before I get long into it I want advice on setting it up and querying it. I set the table like this.
id: primary ket
time_in: date
time_out: date
task: varchar (128)
business: varchar (128)
All I need it to do is to keep track of how much time spent on each task and for what business. Is this good way of doing it or is there a better way?
If this is correct then I am trying to figure out how to query the time. This is what I have come up with as a query, but it far from what I want.
SELECT `Task`,`Business`, (SELECT `Time-Out` - `Time-In`) as `total time` FROM `Sheet`
Is there a way to convert total time into a more readable format?

Unless you're tracking time in days, I'd recommend using TIME or DATETIME for the time_in and time_out columns.
Personally, I'd probably make time_out nullable, to allow tracking current activity (something I've started, but not yet finished).
There's no need to use a sub-select for subtracting the timestamps, you can subtract those two columns inline as well (just drop the SELECT keyword there). For formatting, you could use the TIMEDIFF function:
SELECT '12:00:00' - '10:45:00';
-> 2
SELECT TIMEDIFF('12:00:00', '10:45:00');
-> '01:15:00'
That would make your query:
SELECT `Task`, `Business`, TIMEDIFF(`Time-Out`, `Time-In`) as `total time` FROM `Sheet`
If you do make time_out (or Time-Out) nullable, you'll need to take that into account in your query:
SELECT TIMEDIFF(NULL, '10:45:00');
-> NULL
So ongoing tasks would give a total time of NULL. If you want to know how long you've been working already, you can wrap it in an IFNULL function and get the current time in that case:
SELECT TIMEDIFF(IFNULL(`Time-Out`, NOW()), `Time-In`);
-> '01:15:00' if `Time-Out` is 12:00:00 and `Time-In` is 10:45:00
-> '02:05:13' if `Time-Out` is NULL and it's currently 12:50:13 (server time)

You will want to use TIMEDIFF(end_time, start_time) and TIME_TO_SEC(time) to convert the difference to a total number of seconds. You can then convert the seconds mathematically to whatever format you want.
So for the time of each task:
select ID
,task
,business
,time_to_sec(timediff(time_out, time_in)) as duration
from sheet
To aggregate by task and business:
select task
,business
,sum(time_to_sec(timediff(time_out,time_in))) as total_time
from sheet
group by task
,business

Related

UNIX Timestamp Time Difference Average MYSQL

I am currently working on a ticket system in which I would like to work out the average amount of time it is taking staff to respond to tickets.
I have 2 columns that hold the UNIX timestamps: timestamp (when ticket was submitted) and endstamp (when ticket was closed)
SELECT AVG(TIMEDIFF(endstamp,timestamp)) AS timetaken FROM `tickets`
I'm not really sure what I am doing wrong.
Any help would be much appreciated!
A UNIX timestamp is just a representation of a point in time as a number of seconds, so basically an integer value. On the other hand, date function timestampdiff() operates on 3 parameters: a unit, and two values (or expressions) of datetime datatype (or the-like). Your query should actually raise a syntax error, since what you are giving as first argument is not a legal unit.
If you want the difference in seconds between two UNIX timestamps, just substract them, so:
SELECT AVG(endstamp - timestamp) AS timetaken FROM `tickets`

SQL query doesn't work on a specific day

I have a weird problem in mysql!
my query is
SELECT * FROM aa WHERE problemTime>= '2016/03/20' AND problemTime<= '2016/04/20'
the result of this query is nothing , but when I change the first time to 2016/03/19 or 2016/03/21 I have the following result! I mean these queries
SELECT * FROM aa WHERE problemTime>= '2016/03/21' AND problemTime<= '2016/04/20'
or
SELECT * FROM aa WHERE problemTime>= '2016/03/19' AND problemTime<= '2016/04/20'
the result in both time ( 19th and 21th) is
but when I use 20th the result is noting
my main table is
I change the format of time from 2016/03/20 to 2016-03-20 ( I mean change / to - ) but it doesn't have change too!
whats the problem?
You should really be running a query like this if your problemTime column is datetime type:
SELECT * FROM aa
WHERE
problemTime>= str_to_date('2016/03/20', '%Y/%m/%d') AND
problemTime <= str_to_date('2016/04/20', '%Y/%m/%d')
Don't rely on implicit conversions between string and date.. leave your table data alone and ensure you explicitly convert your where clause parameters to the same data type as in the table. Also remember that a date "without" a time is actually midnight on the day in question, and midnight is like zero, it's the first thing that happens on any given day. A time of 6am on a given date, is after midnight, so a query that asks for dates less than or equal to midnight on a particular date means the 6am date will be excluded
This is general good DB practice; do not convert table data where possible, because it can cause huge performance hits and wrong results
Your column "problemTime" have date with time. Do not convert table data, change your where clause (add time).
SELECT * FROM aa WHERE problemTime>= '2016/03/20 00:00:00' AND problemTime<= '2016/04/20 23:59:59'
Try this as per SQl Server.
SELECT * FROM aa
WHERe cast(problemTime AS date) between '2016/03/21' AND '2016/04/20'

Calculating time difference between activity timestamps in a query

I'm reasonably new to Access and having trouble solving what should be (I hope) a simple problem - think I may be looking at it through Excel goggles.
I have a table named importedData into which I (not so surprisingly) import a log file each day. This log file is from a simple data-logging application on some mining equipment, and essentially it saves a timestamp and status for the point at which the current activity changes to a new activity.
A sample of the data looks like this:
This information is then filtered using a query to define the range I want to see information for, say from 29/11/2013 06:00:00 AM until 29/11/2013 06:00:00 PM
Now the object of this is to take a status entry's timestamp and get the time difference between it and the record on the subsequent row of the query results. As the equipment works for a 12hr shift, I should then be able to build a picture of how much time the equipment spent doing each activity during that shift.
In the above example, the equipment was in status "START_SHIFT" for 00:01:00, in status "DELAY_WAIT_PIT" for 06:08:26 and so-on. I would then build a unique list of the status entries for the period selected, and sum the total time for each status to get my shift summary.
You can use a correlated subquery to fetch the next timestamp for each row.
SELECT
i.status,
i.timestamp,
(
SELECT Min([timestamp])
FROM importedData
WHERE [timestamp] > i.timestamp
) AS next_timestamp
FROM importedData AS i
WHERE i.timestamp BETWEEN #2013-11-29 06:00:00#
AND #2013-11-29 18:00:00#;
Then you can use that query as a subquery in another query where you compute the duration between timestamp and next_timestamp. And then use that entire new query as a subquery in a third where you GROUP BY status and compute the total duration for each status.
Here's my version which I tested in Access 2007 ...
SELECT
sub2.status,
Format(Sum(Nz(sub2.duration,0)), 'hh:nn:ss') AS SumOfduration
FROM
(
SELECT
sub1.status,
(sub1.next_timestamp - sub1.timestamp) AS duration
FROM
(
SELECT
i.status,
i.timestamp,
(
SELECT Min([timestamp])
FROM importedData
WHERE [timestamp] > i.timestamp
) AS next_timestamp
FROM importedData AS i
WHERE i.timestamp BETWEEN #2013-11-29 06:00:00#
AND #2013-11-29 18:00:00#
) AS sub1
) AS sub2
GROUP BY sub2.status;
If you run into trouble or need to modify it, break out the innermost subquery, sub1, and test that by itself. Then do the same for sub2. I suspect you will want to change the WHERE clause to use parameters instead of hard-coded times.
Note the query Format expression would not be appropriate if your durations exceed 24 hours. Here is an Immediate window session which illustrates the problem ...
' duration greater than one day:
? #2013-11-30 02:00# - #2013-11-29 01:00#
1.04166666667152
' this Format() makes the 25 hr. duration appear as 1 hr.:
? Format(#2013-11-30 02:00# - #2013-11-29 01:00#, "hh:nn:ss")
01:00:00
However, if you're dealing exclusively with data from 12 hr. shifts, this should not be a problem. Keep it in mind in case you ever need to analyze data which spans more than 24 hrs.
If subqueries are unfamiliar, see Allen Browne's page: Subquery basics. He discusses correlated subqueries in the section titled Get the value in another record.

Datetime vs Date and Time Mysql

I generally use datetime field to store created_time updated time of data within an application.
But now i have come across a database table where they have kept date and time separate fields in table.
So what are the schema in which two of these should be used and why?
What are pros and cons attached with using of two?
There is a huge difference in performance when using DATE field above DATETIME field. I have a table with more then 4.000.000 records and for testing purposes I added 2 fields with both their own index. One using DATETIME and the other field using DATE.
I disabled MySQL query cache to be able to test properly and looped over the same query for 1000x:
SELECT * FROM `logs` WHERE `dt` BETWEEN '2015-04-01' AND '2015-05-01' LIMIT 10000,10;
DATETIME INDEX:
197.564 seconds.
SELECT * FROM `logs` WHERE `d` BETWEEN '2015-04-01' AND '2015-05-01' LIMIT 10000,10;
DATE INDEX:
107.577 seconds.
Using a date indexed field has a performance improvement of: 45.55%!!
So I would say if you are expecting a lot of data in your table please consider in separating the date from the time with their own index.
I tend to think there are basically no advantages to storing the date and time in separate fields. MySQL offers very convenient functions for extracting the date and time parts of a datetime value.
Okay. There can be some efficiency reasons. In MySQL, you can put separate indexes on the fields. So, if you want to search for particular times, for instance, then a query that counts by hours of the day (for instance) can use an index on the time field. An index on a datetime field would not be used in this case. A separate date field might make it easier to write a query that will use the date index, but, strictly speaking, a datetime should also work.
The one time where I've seen dates and times stored separately is in a trading system. In this case, the trade has a valuation date. The valuation time is something like "NY Open" or "London Close" -- this is not a real time value. It is a description of the time of day used for valuation.
The tricky part is when you have to do date arithmetic on a time value and you do not want a date portion coming into the mix. Ex:
myapptdate = 2014-01-02 09:00:00
Select such and such where myapptdate between 2014-01-02 07:00:00 and 2014-01-02 13:00:00
1900-01-02 07:00:00
2014-01-02 07:00:00
One difference I found is using BETWEEN for dates with non-zero time.
Imagine a search with "between dates" filter. Standard user's expectation is it will return records from the end day as well, so using DATETIME you have to always add an extra day for the BETWEEN to work as expected, while using DATE you only pass what user entered, with no extra logic needed.
So query
SELECT * FROM mytable WHERE mydate BETWEEN '2020-06-24' AND '2020-06-25'
will return a record for 2020-06-25 16:30:00, while query:
SELECT * FROM mytable WHERE mydatetime BETWEEN '2020-06-24' AND '2020-06-25'
won't - you'd have to add an extra day:
SELECT * FROM mytable WHERE mydatetime BETWEEN '2020-06-24' AND '2020-06-26'
But as victor diaz mentioned, doing datetime calculations with date+time would be a super inefficient nightmare and far worse, than just adding a day to the second datetime. Therefore I'd only use DATE if the time is irrelevant, or as a "cache" for speeding queries up for date lookups (see Elwin's answer).

Getting week started date using MySQL

If I have MySQL query like this, summing word frequencies per week:
SELECT
SUM(`city`),
SUM(`officers`),
SUM(`uk`),
SUM(`wednesday`),
DATE_FORMAT(`dateTime`, '%d/%m/%Y')
FROM myTable
WHERE dateTime BETWEEN '2011-09-28 18:00:00' AND '2011-10-29 18:59:00'
GROUP BY WEEK(dateTime)
The results given by MySQL take the first value of column dateTime, in this case 28/09/2011 which happens to be a Saturday.
Is it possible to adjust the query in MySQL to show the date upon which the week commences, even if there is no data available, so that for the above, 2011-09-28 would be replaced with 2011/09/26 instead? That is, the date of the start of the week, being a Monday. Or would it be better to adjust the dates programmatically after the query has run?
The dateTime column is in format 2011/10/02 12:05:00
It is possible to do it in SQL but it would be better to do it in your program code as it would be more efficient and easier. Also, while MySQL accepts your query, it doesn't quite make sense - you have DATE_FORMAT(dateTime, '%d/%m/%Y') in select's field list while you group by WEEK(dateTime). This means that the DB engine has to select random date from current group (week) for each row. Ie consider you have records for 27.09.2011, 28.09.2011 and 29.09.2011 - they all fall onto same week, so in the final resultset only one row is generated for those three records. Now which date out of those three should be picked for the DATE_FORMAT() call? Answer would be somewhat simpler if there is ORDER BY in the query but it still doesn't quite make sense to use fields/expressions in the field list which aren't in GROUP BY or which aren't aggregates. You should really return the week number in the select list (instead of DATE_FORMAT call) and then in your code calculate the start and end dates from it.