Convert Bigint data to human readable date-time in Sql - mysql

I have created a MySql table and feed data therein with below code
CREATE TABLE IF NOT EXISTS DB (
INN VARCHAR(200) NOT NULL,
Time BIGINT not NULL
);
Now I want to get a table which will report the Maximum and Minimum values of Time when grouped by INN. Below is my code -
SELECT INN, from_unixtime(MIN(Time)), from_unixtime(MAX(Time)) FROM DB GROUP BY INN
I want to get the Time values reported as normal date-time instead of Epoch time. But with above code, I am getting <NA> values.
A typical Time value is like 1546380001264082944
Can someone please help me to get the correct code to achieve the same.

The problem here is to do with the precision of the unix timestamp you are using.
Consider this:
SELECT FROM_UNIXTIME(1546380001), FROM_UNIXTIME(1546380001264082944)
The output is:
2019-01-01T22:00:01Z (null)
The timestampt value you have, 1546380001264082944, contains a level of precision beyond that accepted by MySQL.
The definition of FROM_UNIXTIME is:
FROM_UNIXTIME(unix_timestamp[,format])
The doc states:
unix_timestamp is an internal timestamp value representing seconds
since '1970-01-01 00:00:00' UTC
The precision of your timestamp is significantly greater than seconds since the Unix Epoch.
The docs are available here.

The value 1546380001264082944 is too big to be epoch seconds or even milliseconds. This is easily verified by putting this value on https://currentmillis.com/.
You have stored precision upto a nanosecond. So, divide the column value by 1e9 before passing them to from_unixtime.
SELECT INN, from_unixtime(MIN(Time) / 1000000000), from_unixtime(MAX(Time) / 1000000000)
FROM DB
GROUP BY INN

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`

MySQL TIMESTAMP to QDateTime with milliseconds

If I use a QSqlTableModel to access a MySQL database I can convert a TIMESTAMP field using the following:
QDateTime dateTime = index(section, column).data().toDateTime();
QString str = dateTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
So str shows, i.e. 2014-06-22 22:11:44.221.
But I want to access the database using QSqlQuerry, so I do:
QDateTime dateTime = query.value(column).toDateTime();
str = dateTime.toString("yyyy-MM-dd hh:mm:ss.zzz");
But now I'm missing the milliseconds, str shows 2014-06-22 22:11:44.000. What's the proper way to see the milliseconds?
If I do str = query.value(column).toString(); then I get 2014-06-22T22:11:44.
From this page:
https://dev.mysql.com/doc/refman/5.6/en/datetime.html
A DATETIME or TIMESTAMP value can include a trailing fractional
seconds part in up to microseconds (6 digits) precision. In
particular, as of MySQL 5.6.4, any fractional part in a value inserted
into a DATETIME or TIMESTAMP column is stored rather than discarded.
So, the millisecond is there in MySQL! But the query.value() does not get it - at this point in the Qt history as pointed by #peppe here.
Relating back to the original question: There is no proper way to see the millisecond since the query does not have it. One alternative could be to modify the query, from:
SELECT timestamp FROM table;
to
SELECT DATE_FORMAT(timestamp, '%Y-%c-%e %H:%i:%s.%f') as timestamp FROM table;
And then finish the job with:
QString str = query.value(column).toString();
QDateTime dateTime = QDateTime::fromString(str, "yyyy-MM-dd hh:mm:ss.zzz000");
I got the insight from here.
From MySQL 5.1 documentation:
A DATETIME or TIMESTAMP value can include a trailing fractional seconds part in up to microseconds (6 digits) precision. Although this fractional part is recognized, it is discarded from values stored into DATETIME or TIMESTAMP columns.
It seems like seconds is the best you can do with timestamp.

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).

T-SQL Select data from multiple days between certain times

In my table I have minute data about daily temperature measurements. The table looks like:
DateTime timestamp, Float temperature
I would like to have the temperatures on different dates between a certain interval and then only show the temperature between 7am and 8pm.
I know how to get the data between dates:
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
How to I implement the time restriction (7am - 8pm) as well?
Thanks a lot!!
If you are on SQL Server 2008 or above, you can use TIME datatype
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND CONVERT(TIME,[timestamp]) BETWEEN '19:00:00' AND '20:00:00'
EDIT: Also it is recommended to use ISO (yyyymmdd) date format when using date as a string. i.e.
BETWEEN '20121110' and '20121117'
The DateTime and TimeStamp values should contain precision you need, so
SELECT [timestamp],[temperature]
FROM [meteo_data]
WHERE [timestamp] BETWEEN '2012-11-10' and '2012-11-17'
AND RIGHT([timestamp], 12) BETWEEN '19:00:00.000' AND '20:00.00.000'
You may need to adjust how many characters you are evaluating in the RIGHT predicate depending on the precision in your database. But the idea is to take all the parts that constitute the hours, minutes, seconds and miliseconds and restrict that to just those between the hours you require.

How do I get the average time from a series of DateTime columns in SQL Server 2008?

Lets say I have a table that contains the following - id and date (just to keep things simple).
It contains numerous rows.
What would my select query look like to get the average TIME for those rows?
Thanks,
Disclaimer: There may be a much better way to do this.
Notes:
You can't use the AVG() function against a DATETIME/TIME
I am casting DATETIME to DECIMAL( 18, 6 ) which appears to yield a reasonably (+- few milliseconds) precise result.
#1 - Average Date
SELECT
CAST( AVG( CAST( TimeOfInterest AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
#2 - Average Time - Remove Date Portion, Cast, and then Average
SELECT
CAST( AVG( CAST( TimeOfInterest - CAST( TimeOfInterest AS DATE ) AS DECIMAL( 18, 6 ) ) ) AS DATETIME )
FROM dbo.MyTable;
The second example subtracts the date portion of the DATETIME from itself, leaving only the time portion, which is then cast to a decimal for averaging, and back to a DATETIME for formatting. You would need to strip out the date portion (it's meaningless) and the time portion should represent the average time in the set.
SELECT CAST(AVG(CAST(ReadingDate AS real) - FLOOR(CAST(ReadingDate as real))) AS datetime)
FROM Rbh
I know that, in at least some of the SQL standards, the value expression (the argument to the AVG() function) isn't allowed to be a datetime value or a string value. I haven't read all the SQL standards, but I'd be surprised if that restriction had loosened over the years.
In part, that's because "average" (or arithmetic mean) of 'n' values is defined to be the sum of the values divided by the 'n'. And the expression '01-Jan-2012 08:00' + '03-Mar-2012 07:53' doesn't make any sense. Neither does '01-Jan-2012 08:00' / 3.
Microsoft products have a history of playing fast and loose with SQL by exposing the internal representation of their date and time data types. Dennis Ritchie would have called this "an unwarranted chumminess with the implementation."
In earlier versions of Microsoft Access (and maybe in current versions, too), you could multiply the date '01-Jan-2012' by the date '03-Mar-2012' and get an actual return value, presumably in units of square dates.
If your dbms supports the "interval" data type, then taking the average is straightforward, and does what you'd expect. (SQL Server doesn't support interval data types.)
create table test (
n interval hour to minute
);
insert into test values
('1:00'),
('1:30'),
('2:00');
select avg(n)
from test;
avg (interval)
--
01:30:00