Easiest way to convert timestamp_ntz to timestamp_tz in Snowflake database - snowflake-cloud-data-platform

I have a Timestamp_NTZ column where I know the data are in Central (America/Chicago) timezone. How do I convert it into Timestamp_TZ format during select.
I couldn't just convert to varchar and add timezone offset and back to timestamp_tz because of different offset during daylight saving.
I found following two approaches but they involves more code/typing. Looking for elegant solution.
Alter session to the required timezone and use TO_TIMESTAMP_TZ() function. The drawback of this approach is that its two separate query and it cannot be used in stored procedure with run as Owner.
alter session set timezone = 'America/Chicago';
select TO_TIMESTAMP_TZ(column_name) from table_name;
Use TIMESTAMP_TZ_FROM_PARTS function. This involves more typing and looks complicated.
select TIMESTAMP_TZ_FROM_PARTS(Year(column_name), Month(column_name), Day(column_name), Hour(column_name), Minute(column_name), Second(column_name), 0, 'America/Chicago') from table_name;
Is there a simple way to do this in snowflake, something like:
select TO_TIMESTAMP_TZ(column_name, 'America/Chicago') from table_name;

You should be able to use the CONVERT_TIMEZONE for this. The 2 argument version Doesn't expect TIMESTAMP_TZ as you mentioned in your comment. You can see below that I'm passing in a TIMESTAMP_NTZ for demonstration purposes but you could pass in a string like 2020-01-27T08:00:00Z too if you want:
select CONVERT_TIMEZONE( 'America/Chicago' , TO_TIMESTAMP_NTZ('2020-01-27T08:00:00Z'));
The above returns
2021-01-26 02:00:00.000000000 -06:00

Related

Snowsql two digit century start date cast issue

I want a result 2000-02-05 with below query in snowsql.
alter session set TWO_DIGIT_CENTURY_START=2000;
select cast ('05-FEB-00' as date) from dual;
But I am getting 0001-02-05.
I am using existing script to load date in snowflake which works for oracle. I know I can get expected result using to_date function but I don't want to do so. If I have to then I have change many place in script which is hectic.
I want solution using cast function. Do anyone know what is happening here?
You first need to specify the non-default date format for your input data. In the case of the example above:
alter session set date_input_format = 'DD-MON-YY';
Then
alter session set TWO_DIGIT_CENTURY_START=2000;
select cast ('05-FEB-00' as date) from dual;
yields:
2000-02-05

SQL Server date formatting issue

I have a SQL Server 2008 database with a transaction table. There is a field defined as NVARCHAR(16). The data stored is date and time formatted like this:
2016100708593100
I need to write a query that looks at that field and pulls data between two dates
select ... from...where convert(varchar,
convert(datetime,left(a.xact_dati,8)),101)
between '9/29/2016' and '10/05/2016'
I have tried other converts but nothing returns any data. If I use >=getdate()-1
I get data so I should be seeing something returned. Any suggestions?
Replace WHERE Clause with
... WHERE CONVERT(DATETIME,LEFT(a.xact_dati,8)) BETWEEN '9/29/2016' AND '10/05/2016'
Assuming YMD order just
where cast(left('2016100708593100', 8) as date) between '20160929' and '20161005'
Note this clause is not satisfied.
The problem is you're trying to do a date comparison with varchar data.
You go half way to converting the initial value to datetime but then back to varchar.
You could rely on Sql to implicitly convert the between parameters to datetime.
select 'matched',convert(datetime,left('2016100708593100',8),112)
where convert(datetime,left('2016100708593100',8),112) between '2016/09/29' and '2016/10/10'
Take the date part of the string and CAST it as DATE and then compare it with the proper date format.
select ... from...
where cast(left('2016100708593100', 8) as date) between '2016-09-29' and '2016-10-10'
a very straight and fast approach could be to keep this in BIGINT
Something like this:
cast(left(a.xact_dati,8) as bigint) between 20160929 and 20161005
But anyway this will not be sargable and therefore cannot use an index.
You might even stick to varchar, as the YYYYMMDD format is safe with alphanumerical sorting. Cutting a string with LEFT is sargable (AFAIK):
left(a.xact_dati,8) between '20160929' and '20161005'

How to set date format for the result of a SELECT statement in SQL Server

I know how to use CONVERT function in SELECT statement to change the format of the Date column:
SELECT
StationID
, CONVERT(varchar, [Date], 101) as Date
, Value
FROM my_table
But I was wondering if I can set the date format in general before running the SELECT statement, when I don't know the name of the date column in the following SELECT statement:
SELECT * from FROM my_table
Is any SET statement or other T-SQL that I can run before my SELECT statement so that I can change the Date format temporarily?
Thank you
No.
In particular, any date columns which you select are not actually formatted at all, but are instead returned down the wire as an actual piece of date data in a binary "format" which is used for dates. If you are seeing them formatted, it's because your client (either management studio or some other tool) is converting them to strings to display.
When you use SELECT *, there is obviously no way to tell SQL Server to do any conversions on any particular columns, so the data is going to be returned in whatever the data types of the underlying query returns. So regardless of whether your data types are really date or not, no manipulation is going to happen at that point anyway.
I'm pretty sure there's no way to do what you're asking. However, there are ways to format the date string when you output it using your programming language.

Simulate current date on a SQL Server instance?

Is it possible to change the datetime for a particular database on SQL Server?
Is it tied to the operating system's date/time?
We wish to simulate a future datetime for testing purposes i.e. so the GETDATE() returns a date in the future.
It's got to be in a semi-production (staging) environment so unfortunately changing the OS date / time isn't an option for us.
In an ideal world we'd spin up a virtual server, but also not really an option at the moment.
As stated, by others, No.
A really hacky workaround, would be be to write your own function to return the date you want and have it return GETDATE() when you're done testing, and call that function instead. There's probably some slight overhead in doing this, but it'll do what you need.
Unfortunately it is tied to the OS date and time. See here: http://msdn.microsoft.com/en-us/library/ms188383.aspx
This value is derived from the operating system of the computer on
which the instance of SQL Server is running.
You can always use this and adjust accordingly:
SELECT getutcdate()
Please see below for more information
StackOverflow Question
But there is no way to change the results from a GETDATE() without changing the server's date.
Added:
You could do a EXEC xp_cmdshell 'DATE 10/10/2011' if you wish... but it's not advised.
Another workaround I've had some success with is to add an INSTEAD OF trigger to any table where a GETDATE() value is being inserted and modify it there e.g.:
ALTER TRIGGER [dbo].[AccountsPayableReceivable_trg_i] ON [dbo].[AccountsPayableReceivable]
INSTEAD OF INSERT
AS
SET NOCOUNT ON
SELECT *
INTO #tmp_ins_AccountsPayableReceivable
FROM INSERTED
UPDATE #tmp_ins_AccountsPayableReceivable
SET dtPaymentMade = '01-Jan-1900'
WHERE dtPaymentMade between dateadd(ss, -5, getdate()) and dateadd(ss, +5, getdate())
INSERT INTO AccountsPayableReceivable
SELECT *
from #tmp_ins_AccountsPayableReceivable
(Incidentally, the where clause is there because my test script autogenerates these triggers, adding an update for every datetime column, so I only want to update those that look like they are being inserted with a GETDATE() value.)
I believe you can create a user function that would do the calculation for you and apply that.
http://msdn.microsoft.com/en-us/library/ms186755.aspx
Also, it can be used as the default value for a column.
Bind a column default value to a function in SQL 2005

How to convert SQL Server's timestamp column to datetime format

As SQL Server returns timestamp like 'Nov 14 2011 03:12:12:947PM', is there some easy way to convert string to date format like 'Y-m-d H:i:s'.
So far I use
date('Y-m-d H:i:s',strtotime('Nov 14 2011 03:12:12:947PM'))
SQL Server's TIMESTAMP datatype has nothing to do with a date and time!
It's just a hexadecimal representation of a consecutive 8 byte integer - it's only good for making sure a row hasn't change since it's been read.
You can read off the hexadecimal integer or if you want a BIGINT. As an example:
SELECT CAST (0x0000000017E30D64 AS BIGINT)
The result is
400756068
In newer versions of SQL Server, it's being called RowVersion - since that's really what it is. See the MSDN docs on ROWVERSION:
Is a data type that exposes automatically generated, unique binary numbers within a database. rowversion is generally used as a mechanism
for version-stamping table rows. The
rowversion data type is just an incrementing number and does not
preserve a date or a time. To record a date or time, use a datetime2
data type.
So you cannot convert a SQL Server TIMESTAMP to a date/time - it's just not a date/time.
But if you're saying timestamp but really you mean a DATETIME column - then you can use any of those valid date formats described in the CAST and CONVERT topic in the MSDN help. Those are defined and supported "out of the box" by SQL Server. Anything else is not supported, e.g. you have to do a lot of manual casting and concatenating (not recommended).
The format you're looking for looks a bit like the ODBC canonical (style = 121):
DECLARE #today DATETIME = SYSDATETIME()
SELECT CONVERT(VARCHAR(50), #today, 121)
gives:
2011-11-14 10:29:00.470
SQL Server 2012 will finally have a FORMAT function to do custom formatting......
The simplest way of doing this is:
SELECT id,name,FROM_UNIXTIME(registration_date) FROM `tbl_registration`;
This gives the date column atleast in a readable format.
Further if you want to change te format click here.
Using cast you can get date from a timestamp field:
SELECT CAST(timestamp_field AS DATE) FROM tbl_name
Works fine, except this message:
Implicit conversion from data type varchar to timestamp is not allowed. Use the CONVERT function to run this query
So yes, TIMESTAMP (RowVersion) is NOT a DATE :)
To be honest, I fidddled around quite some time myself to find a way to convert it to a date.
Best way is to convert it to INT and compare. That's what this type is meant to be.
If you want a date - just add a Datetime column and live happily ever after :)
cheers mac
My coworkers helped me with this:
select CONVERT(VARCHAR(10), <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(VARCHAR(10), <tms_column>, 112);
or
select CONVERT(DATE, <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(DATE, <tms_column>, 112);
"You keep using that word. I do not think it means what you think it means."
— Inigo Montoya
The timestamp has absolutely no relationship to time as marc_s originally said.
declare #Test table (
TestId int identity(1,1) primary key clustered
,Ts timestamp
,CurrentDt datetime default getdate()
,Something varchar(max)
)
insert into #Test (Something)
select name from sys.tables
waitfor delay '00:00:10'
insert into #Test (Something)
select name from sys.tables
select * from #Test
Notice in the output that Ts (hex) increments by one for each record, but the actual time has a gap of 10 seconds. If it were related to time then there would be a gap in the timestamp to correspond with the difference in the time.
for me works:
TO_DATE('19700101', 'yyyymmdd') + (TIME / 24 / 60 / 60)
(oracle DB)
Robert Mauro has the correct comment. For those who know the Sybase origins, datetime was really two separate integers, one for date, one for time, so timestamp aka rowversion could just be considered the raw value captured from the server. Much faster.
After impelemtation of conversion to integer
CONVERT(BIGINT, [timestamp]) as Timestamp
I've got the result like
446701117
446701118
446701119
446701120
446701121
446701122
446701123
446701124
446701125
446701126
Yes, this is not a date and time, It's serial numbers
Why not try FROM_UNIXTIME(unix_timestamp, format)?
I had the same problem with timestamp eg:'29-JUL-20 04.46.42.000000000 PM'. I wanted to turn it into 'yyyy-MM-dd' format. The solution that finally works for me is
SELECT TO_CHAR(mytimestamp, 'YYYY-MM-DD') FROM mytable;
I will assume that you've done a data dump as insert statements, and you (or whoever Googles this) are attempting to figure out the date and time, or translate it for use elsewhere (eg: to convert to MySQL inserts). This is actually easy in any programming language.
Let's work with this:
CAST(0x0000A61300B1F1EB AS DateTime)
This Hex representation is actually two separate data elements... Date and Time. The first four bytes are date, the second four bytes are time.
The date is 0x0000A613
The time is 0x00B1F1EB
Convert both of the segments to integers using the programming language of your choice (it's a direct hex to integer conversion, which is supported in every modern programming language, so, I will not waste space with code that may or may not be the programming language you're working in).
The date of 0x0000A613 becomes 42515
The time of 0x00B1F1EB becomes 11661803
Now, what to do with those integers:
Date
Date is since 01/01/1900, and is represented as days. So, add 42,515 days to 01/01/1900, and your result is 05/27/2016.
Time
Time is a little more complex. Take that INT and do the following to get your time in microseconds since midnight (pseudocode):
TimeINT=Hex2Int(HexTime)
MicrosecondsTime = TimeINT*10000/3
From there, use your language's favorite function calls to translate microseconds (38872676666.7 µs in the example above) into time.
The result would be 10:47:52.677
Some of them actually does covert to a date-time from SQL Server 2008 onwards.
Try the following SQL query and you will see for yourself:
SELECT CAST (0x00009CEF00A25634 AS datetime)
The above will result in 2009-12-30 09:51:03:000 but I have encountered ones that actually don't map to a date-time.
Not sure if I'm missing something here but can't you just convert the timestamp like this:
CONVERT(VARCHAR,CAST(ZEIT AS DATETIME), 110)

Resources