How to truncate seconds in TSQL? - tsql

I have time, select cast(SYSDATETIME() AS time)
14:59:09.2834595
What is the way to truncate seconds?
14:59

Description
You can use the T-SQL function convert.
Sample
PRINT convert(varchar(5), SYSDATETIME(), 108)
will give you hh:mm
More Information
MSDN - CAST and CONVERT

If you want to truncate seconds and still have a T-SQL Date datatype, first convert the date into minutes from the date '0' and then add the minutes back to '0'. This answer doesn't require any additional parsing/converting. This method works to truncate other parts just change MINUTE.
Example:
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, '2016-01-01 23:22:56.997'), 0)

If you need to drop seconds off entirely, you can use the DATEPART() function (SQL Server) to strip out the hour and minute, then append it back together. (I like dknaack's solution more, if that works.)
SELECT CAST(DATEPART(hour, SYSDATETIME()) + ':' + DATEPART(minute, SYSDATETIME()) AS DATETIME)

select cast(left(cast(SYSDATETIME() AS time), 5) as time)

Related

Can't extract date from milliseconds epoch postgresql

I'm querying the database (RedShift) and I have a piece of information stored in epoch MS format. Envision a table along the lines of:
Purchase, date
1, 1620140227019
2, 1620140227045
3, 1620140226573
I need to convert the timestamp to a readable date but I can't make it work with to_timestamp() or extract(). The problem is first with the size of the value (13 digits are not supported).
The closest solution I have is
select to_timestamp(1620140226573/1000, 'SS')
But the result is 0051-05-04 14:57:06. In other words month, date and seconds are correct but the year is wrong.
You can run this query
select to_timestamp(round(1620140227254/1000))
The solution was in the documentation: https://docs.aws.amazon.com/redshift/latest/dg/r_Dateparts_for_datetime_functions.html
SELECT timestamp with time zone 'epoch' + 1620140227019/1000 * interval '1 second' AS converted_timestamp
or
select '1970-01-01'::date + 1620140227019/1000 * interval '1 second'

Convert to_timestamp in postgreSQL

Lets do the following:
SELECT to_timestamp(1453336500)::date
Then i get a date 2016-01-21
How does the function work backwards. With the date as input and the number (i guess seconds from 1970) as result?
You use extract:
SELECT extract(epoch FROM current_timestamp);

T-sql issue with coverting bigint to datetime

I have bigint value 635107999009730000.
I'm using this statement to convert this bigint to datetime:
select dateadd(second, 635107999009730000 /1000 + 635107999009730000 % 1000 + 8*60*60, '19700101')
I'm getting overflow error. Looks like dateadd function just cannot handle this bigint value.
How can I convert 635107999009730000 to datetime?
635107999009730000 value is grabbed from Microsoft LYNC 2013 database and I don't really know what datetime this should be.
I may be off the mark here but that value looks like nanoseconds and if that is the case you just have to divide it by a billion to get the seconds and add it to the unix time:
select dateadd(second, 635107999009730000 / 1000000000, '19700101')
You will have to test this against you data.
I ran into the same issue today. Both user1016945 and Suroh are correct to a degree. It is 10^7 ticks per second staring with 0001-01-01. So I slightly modified Suroh's statement. Since i'm not SQL expert, it's clumsy, but it work. You will lose seconds though. It overflows if I try to include seconds:
dateadd(year, -2000, dateadd(minute, 635107999009730000 / 600000000, '2001-01-01'))
I subtract 2000 years because I don't know how to pass 0001-01-01 to SQL. :)

Datatype of Hour in oracle

When we use the query like this in oracle to get the the total number of hours in round figure,
hours= select round(out_time-in_time)*24 from table_name;
what is the datatype of hours here?
out_time and in_time are column names
You can take NUMBER as the datatype in your case.
EDIT:- This will return you an integer
select 24 * round((to_date('2013-07-07 22:00', 'YYYY-MM-DD hh24:mi')
- to_date('2013-07-07 19:30', 'YYYY-MM-DD hh24:mi'))) diff_hours
from table_name;
Maybe a datatype called "INTERVAL" will suit you. It's called:
INTERVAL DAY [(day_precision)] TO SECOND
Stores a period of time in days, hours, minutes, and seconds
Interval is something that can we added (or substrated) to a DATE or TIMESTAMP.
see: http://docs.oracle.com/cd/E11882_01/server.112/e26088/sql_elements001.htm

Postgresql. Dates interval issue

I'm trying to get difference in days, casting result to decimal:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd') AS DECIMAL )
;
Now if I add 1 month to the 2nd date:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DECIMAL )
;
I'm getting an error:
ERROR: cannot cast type interval to numeric
OK, I can cast to char to get result:
SELECT
CAST( TO_CHAR( TO_DATE('2909-02-10','yyyy-mm-dd') - (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ), 'DD') AS DECIMAL )
;
But in this case the 1st query modified with TO_CHAR casting stop working:
SELECT
CAST( TO_CHAR(TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'), 'DD') AS DECIMAL )
;
I'm getting ERROR: multiple decimal points.
So, my question is, how can I get days using the same sql statement? For both sql queries.
Look at your first two examples again. If you remove the outer CAST ... AS DECIMAL you get
?column?
----------
32872
?column?
------------
32841 days
Clearly the difference is in the "days". The second is an interval value rather than a simple number. You only want the number (because you always just want days) so you need to extract that part. Then you can cast to whatever precision you like:
SELECT extract(days FROM '32841 days'::interval)::numeric(9,2);
date_part
-----------
32841.00
Edit responding to Alexandr's follow-up:
Your first example fails with a fairly specific error:
SELECT extract(days FROM (TO_DATE('2999-01-01','yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval)::numeric(9,2);
ERROR: cannot cast type integer to interval
LINE 1: ...yyyy-mm-dd') - TO_DATE('2909-01-01','yyyy-mm-dd'))::interval...
Here you've got an integer (which is what you originally wanted) and try to cast it to an interval (for reasons I don't understand). It's complaining it doesn't know what units you want. You want 32872 what in your interval - seconds, hours, weeks, centuries?
The second example is complaining because you are trying to extract the "day" part from a simple integer, and of course there's no extract() function in the system to do that.
I think you probably need to take a step back and just take the time to understand the values your various expressions return.
Subtracting one date from another gives the number of days separating them - as an integer. There is no other sensible measure, really.
Adding (or subtracting) an interval to a date gives you a timestamp (without time zone) since the interval may contain whole days, days and hours, seconds etc.
Subtracting a timestamp from a date will give you an interval since the result may contain days, hours, seconds etc.
If you have an interval and you just want the days part then you use extract() on it and you will get an integer number of days back.
You will need an integer (or floating-point) number of days if you want to cast to numeric, not an interval because casting an interval to an scalar number makes no sense without units.
So - either stick to dates and date arithmetic (easy), or realise you are using timestamps (flexible) but understand which it is.
To get an illustration of what's happening you can do something like this (in psql):
CREATE TEMP TABLE tt AS SELECT
('2909-01-02'::date - '2909-01-01'::date) AS a,
('2909-01-02'::date - '2909-01-02 00:00:00'::timestamp) AS b;
\x
SELECT * FROM tt;
\d tt
That will show you the values and types you are dealing with. Repeat for as many columns as you find useful.
HTH
If you're doing interval arithmetic with dates, you should generally be using timestamps instead, as mentioned in the docs.
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - TO_TIMESTAMP('2909-01-01','yyyy-mm-dd'))
date_part
-----------
32872
# SELECT extract(days FROM TO_TIMESTAMP('2999-01-01','yyyy-mm-dd') - (TO_TIMESTAMP('2909-01-01','yyyy-mm-dd') + '1 month'::interval) );
date_part
-----------
32841
The result of adding an interval to a date is actually a timestamp, not another date (the interval might have contained time portions), so you have to cast the result of the addition back down to date first:
SELECT
CAST( TO_DATE('2999-01-01','yyyy-mm-dd')
- CAST( (TO_DATE('2909-01-01','yyyy-mm-dd') + INTERVAL '1 MONTH' * (1) ) AS DATE)
AS DECIMAL )