T-SQL Select data from multiple days between certain times - sql-server-2008

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.

Related

Calculate the difference in hours between two String dates in MySQL?

I have two String columns in MySQL database. Those two columns were populated from a Java program in following way:
System.currentTimeMillis(); //first column
System.currentTimeMillis(); + someStringHours //second column; the String, someStringDays reprensents some number of days, let's say 5 hours in millis...
Which function in MySQL can be used to calculated the difference to get number of hours between these two columns?
You call them string dates but they are actually UNIX timestamps in milliseconds (also called Javascript timestamps). That's what System.currentTimeMillis() generates. It's a Java long data item, and a MySQL BIGINT data item. You can store it in a string. (You can store it that way if you must, but searching and sorting numbers stored as strings is an unreliable mess; beware!)
A typical Javascript timestamp (or UNIX timestamp in milliseconds) is a big integer like 1600858176374456. 1 600 858 176 374 456.
You can convert such a timestamp to a MySQL TIMESTAMP value with FROM_UNIXTIME() like this
FROM_UNIXTIME(column * 0.001)
Why multiply the column value by 0.001 (that is, divide it by 1000)? Because FROM_UNIXTIME() takes the timestamp in seconds, whereas System.currentTmeMillis() generates it in milliseconds.
Then you can use DATEDIFF() like this
DATEDIFF(FROM_UNIXTIME(laterTs*0.001),FROM_UNIXTIME(earlierTs*0.001))
This gives an integer number of days.
If you need the time difference in some other unit, such as hours, minutes, or calendar quarters, you can use TIMESTAMPDIFF(). This gives you your difference in hours.
TIMESTAMPDIFF(HOUR,
FROM_UNIXTIME(laterTs*0.001),
FROM_UNIXTIME(earlierTs*0.001));
You can use SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, or YEAR as the time unit in this function.
Pro tip: Use your DBMS's date arithmetic functions if you possibly can. They've worked out all sorts of edge cases for you already.
And, by the way, if you declare your columns like this (Timestamp with a millisecond precision: How to save them in MySQL):
laterTs TIMESTAMP(3),
earlierTs TIMESTAMP(3),
You'll have an easier time indexing on and searching by these times.
SELECT (1600858176374-1600944576374)/(24*60*60*1000) as Days
Where (1600858176374-1600944576374) are timestamps and (246060*1000) is a mills in day

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`

Convert Bigint data to human readable date-time in Sql

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

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

Time Over 23:59:59 in PostgreSQL?

In MySQL I can create a table with a time field, and the value can be as high as 838:59:59 (839 hours - 1 second). I just read that in PostgreSQL, the hour field cannot exceed 23:00:00 (24 hours). Is there a way around this? I'm trying to make a simple DB that keeps track of how many hours & minutes were spent doing something, so it'll need to go higher than 23 hours & some minutes. I can do this in MySQL, but I need to use PostgreSQL for this. I Googled, but didn't find what I'm looking for, so I'm hoping I just didn't use the right keywords.
Postgres has no "hour field" - it has a few date/time types which serve different needs. The type I believe best fits your needs is INTERVAL.
Although they use the same notation, there's a difference between time of day and elapsed time. Some of their values overlap, but they're different domains. 838 isn't a valid value for an hour if you're talking about a time of day. 838 is a valid value for an hour if you're talking about elapsed time.
This distinction leads to two different data types: timestamp and interval.
create table intervals (
ts timestamp primary key,
ti interval not null
);
insert into intervals values (current_timestamp, '145:23:12');
select *
from intervals;
2011-08-03 21:51:16.837 145:23:12
select extract(hour from ti)
from intervals
145
I believe you are right, but It should not be an issue to work around. Would suggest storing the UNIX time integers for when you "punch in" and out again, and then adding the delta to an int field.
This will yield the number of seconds spent, which can be translated trivially into an hours:minutes:seconds format.
The delta (difference) can be calculated by subtracting the start timestamp from the end timestamp.
you could use a datetime field... 839 hours being something on the order 34.9 days...