Snowflake SQL convert date 'YYYY-MM-DD' to 'DD-MM-YYYY' - sql

I have a table in which date is stored in a dimension table.
I am using this table to retrieve the latest reporting week.
SELECT MAX("Week") AS "Date" FROM "DWH"."DimWeek"
This returns a table with the following date that is in 'YYYY-MM-DD'
+--------------------+
| Date |
|--------------------+
| 2017-01-03 |
+--------------------+
I wish to convert this date, so it returns a format of 'DD-MM-YYYY'
I have attempted to use
SELECT TO_DATE(MAX("Week"), 'DD-MM-YYYY') AS "Date" FROM "DWH"."DimWeek"
SQL Error
too many arguments for function [TO_DATE(MAX("Week", 'DD-MM-YYYY')] expected 1, got 2
I have also attempted to convert it to CHAR
SELECT TO_DATE(TO_CHAR(MAX("Week")), 'DD-MM-YYYY') AS "Date" FROM "DWH"."DimWeek"
However this also returns the result in the undesired format
+--------------------+
| Date |
|--------------------+
| 2017-01-03 |
+--------------------+
Any tips or ideas? Currently querying from Snowflake SQL

Use TO_CHAR(). You want a string in the result, not a date:
SELECT TO_CHAR(MAX("Week")), 'DD-MM-YYYY') AS Date
FROM "DWH"."DimWeek"

Related

BigQuery: Format ISO Date

I'm trying to parse a timestamp which is in ISO Date 8601 format.
Example: 2021-04-10T14:11:00Z
This information is stored inside a JSON object and for that reason I'm extracting that data as a string:
The format I'm looking for is a yy-MM-dd hh:mm format and for that I've tried the following
SQL CODE
SELECT document_id,
json_extract(data, '$.Pair') as pair,
PARSE_TIMESTAMP('%y-%m-%d %H:%M', json_extract(data, '$.AlertTime')) as alerttime,
COUNT(document_id) as alert_count
FROM `tradingview-alerts-26eb8.alltables.TradingView_000_raw_latest` as alert_view
GROUP BY alerttime, document_id, pair
Errors
The code from above causes the following error:
Failed to parse input string '"2021-04-10T03:17:00Z"
The reason for this is the T in the middle of the date, I believe,
In order to discard that I tried this change:
SUBSTR(json_extract(data, '$.AlertTime'), 1, 10))
But with that I'm getting an error on a different row:
Failed to parse input string '"2021-04-1'
I'm wondering if it is because of how the date is being presented (year-month-date) the date not having 2 digits? such as 2021-04-01 instead of 2021-04-1.
However if I try with
SUBSTR(json_extract(data, '$.AlertTime'), 1, 11))
The error I'm getting is
Failed to parse input string '"2021-04-10'
You need to include those ISO symbols into format specifier as constants:
select parse_timestamp('%FT%TZ', '2021-04-12T17:38:10Z')
| f0_ |
---------------------------
| 2021-04-12 17:38:10 UTC |
UPD: If you have fractional seconds, you can include optional milliseconds element %E*S instead of time element %T. For non-UTC timestamps there should also be timezone element: %Ez. So, the possible solution could be:
with a as (
select '2021-04-12T20:44:06.95841Z' as ts_str union all
select '2021-04-12T23:44:07.83738+03:00' union all
select '2021-04-12T23:44:08+03:00'
)
select parse_timestamp('%FT%H:%M:%E*S%Ez', regexp_replace(ts_str, 'Z$', '+00:00')) as ts
from a
| ts |
|--------------------------------|
| 2021-04-12 20:44:06.958410 UTC |
| 2021-04-12 20:44:07.837380 UTC |
| 2021-04-12 20:44:08 UTC |
I think you can use timestamp => datetime func.
Like this
datetime(timestamp(2021-11-29T00:00:00.000Z))

Literal does not match format string error When calculating the difference between two dates in oracle

I want to calculate the difference between two dates, and get the day difference between these dates in Oracle.
Here is my code:
Select To_Date(TO_CHAR(sysdate, 'YYYY/MM/DD','nls_calendar=persian'))- TO_Date(TO_CHAR(SHF_Date))
from DtTable
But I get this error:
ORA-01861: literal does not match format string for case statement
sysdate is already a date, and shf_date also seems to be one. You don't need any conversion here, and can subtract them directly:
SELECT sysdate - SHF_Date FROM DtTable
If you want to use your statement
Select To_Date( TO_CHAR(sysdate, 'YYYY/MM/DD','nls_calendar=persian'), 'YYYY/MM/DD')- TO_Date(TO_CHAR(SHF_Date, 'YYYY/MM/DD'), 'YYYY/MM/DD') from DtTable;
But it does not make any sense.
Use it in this way
Select sysdate - hire_date from employees;
Storage format and display format are two different things. We let Oracle store data using its own internal format, which for DATE columns is a 7-byte binary value that is not human-readable.
How you choose to present the values in a report or application is another thing - for example, you could display the same number as 1000, 1,000 or 1e3, or display the same date as 2021-04-18 or Sunday 18th April. This is not related to how you store it. You cannot store any preferred display format. You have to handle the display format when you query it or in your application.
Also, in Oracle date arithmetic, subtracting one date from another gives a number of days, so trying to query to_date(date2 - date1) will never work, because how can it convert a number of days like 270 into a date?
create table dttable (shf_date date);
insert into dttable (shf_date)
values (to_date('1399/05/01','YYYY-MM-DD', 'nls_calendar=Persian'));
(Notice the definition of shf_date as an Oracle date. Is that how it is in your table?)
select to_char(shf_date, 'YYYY-MM-DD', 'nls_calendar=Gregorian') as shf_date_gregorian
, to_char(shf_date, 'YYYY-MM-DD', 'nls_calendar=Persian') as shf_date_shamsi
, trunc(sysdate - shf_date) as days_since_shf_date
from dttable;
SHF_DATE_GREGORIAN SHF_DATE_SHAMSI DAYS_SINCE_SHF_DATE
-------------------- --------------- -------------------
2020-07-22 1399-05-01 270
Although you've said several times that shf_date is a date, you've also said things like:
sysdate is : DD/MM/YYYY but shf_date is : YYYY/MM/DD
I run this code: select trunc(sysdate - shf_date) from dttable; but I get 'Invalid number' error.
Which means it is not a date, but is stored as a string. So, you need to convert that string to a date, in Gregorian calendar, so that actual date can be compared with sysdate.
Modifying and expanding William's example:
select sysdate as sysdate_date
, to_char(sysdate, 'YYYY-MM-DD', 'nls_calendar=Gregorian') as sysdate_gregorian
, to_char(sysdate, 'YYYY-MM-DD', 'nls_calendar=Persian') as sysdate_shamsi
, shf_date as shf_date_string
, to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian') as shf_date_date
, to_char(to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian'), 'YYYY-MM-DD', 'nls_calendar=Gregorian') as shf_date_gregorian
, to_char(to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian'), 'YYYY-MM-DD', 'nls_calendar=Persian') as shf_date_shamsi
, trunc(sysdate - to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian')) as days_since_shf_date
from dttable;
SYSDATE_DATE | SYSDATE_GREGORIAN | SYSDATE_SHAMSI | SHF_DATE_STRING | SHF_DATE_DATE | SHF_DATE_GREGORIAN | SHF_DATE_SHAMSI | DAYS_SINCE_SHF_DATE
:----------- | :---------------- | :------------- | :-------------- | :------------ | :----------------- | :-------------- | ------------------:
18-APR-21 | 2021-04-18 | 1400-01-29 | 1399/05/01 | 22-JUL-20 | 2020-07-22 | 1399-05-01 | 270
db<>fiddle
If you want to use this in a filter then you can do:
where trunc(sysdate - to_date(shf_date, 'YYYY/MM/DD', 'nls_calendar=Persian')) = 270
or whatever comparison you need to perform.

How to deal with Snowflake to_date cast issue with multiple date formats in same column?

The query in snowflake,
select date_column, try_to_date(date_column)
from tablename;
tends to mess up the intended dates as shown below:
01-NOV-18 ____________ 0018-11-01 (desired output 2018-11-01)
09-JAN-19 ____________ 0019-01-09
2018-11-03 20:44:54 __ 2018-11-03
2018-09-03 00:00:00 __ 2018-09-03
2018-08-22 19:38:41 __ 2018-08-22
This is similar to Snowsql two digit century start date cast issue, but with multiple date formats in the input column.
You could use a coalesce with the try_to_date. The key is to specifically put a date format in the try_to_date function so that it returns null if it can't convert a date that doesn't match the format. When the date doesn't match the format it'll fall back to the next method you specify and you can continue until you covered all your different date formats. Try something like:
select
date_column,
coalesce(try_to_date(date_column, 'YYYY-MM-DD HH:MI:SS'), try_to_date(date_column, 'DD-MON-YY'))
from tablename;
This returns:
+-------------------+----------------------------------------------------------------------------------------------+
|INPUT_DATE |COALESCE(TRY_TO_DATE(INPUT_DATE, 'YYYY-MM-DD HH:MI:SS'), TRY_TO_DATE(INPUT_DATE, 'DD-MON-YY'))|
+-------------------+----------------------------------------------------------------------------------------------+
|01-NOV-18 |2018-11-01 |
|09-JAN-19 |2019-01-09 |
|2018-11-03 20:44:54|2018-11-03 |
|2018-09-03 00:00:00|2018-09-03 |
|2018-08-22 19:38:41|2018-08-22 |
+-------------------+----------------------------------------------------------------------------------------------+

Date format with UTC

I have to select the value 2019-03-25 from a date column of a table but in the following format:
2019-03-25T00:00:00.000+02:00
Hon can I get it?
Oracle 10g
Thanks!
The date datatype does not store milliseconds and timezone information, so I undertand your question as how to format a date to the target forma, with fixed values for milliseconds and timezone.
If so, you can use to_char() like so:
to_char(mycol, 'yyyy-mm-dd"T"hh24:mi:ss".000+2:00"')
You can CAST your DATE to a TIMESTAMP and then use FROM_TZ to set the time zone and then format it to your requirements using TO_CHAR:
SELECT TO_CHAR(
FROM_TZ( CAST( your_date AS TIMESTAMP ), '+02:00' ),
'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM'
) AS formatted_date
FROM your_table;
Which, for your sample data:
CREATE TABLE your_table ( your_date ) AS
SELECT DATE '2019-03-25' FROM DUAL
Outputs:
| FORMATTED_DATE |
| :---------------------------- |
| 2019-03-25T00:00:00.000+02:00 |
db<>fiddle here
We can not store timezone information in db that's why we can simply use below format,
select to_char(sysdate,'YYYY-MM-DD')||'T'||to_char(sysdate,'HH24:MI:SS') from dual

Oracle to_date() return incorrect date with +2 days

Oracle to_date() function return incorrect date with +2 days.
Please take a look on screenshot
Why is it happened?
I can't replicate your result, but I do get the wrong date for 1-MAY-18 on SQL Fiddle even if a date literal is used (but not if I use my Oracle 11g instance or Oracle 18c on Oracle's Live SQL website):
SQL Fiddle
Query 1:
SELECT TO_DATE( '1-MAY-18', 'DD-MON-YYYY' ),
DATE '0018-05-01',
TO_DATE( '1-MAY-18', 'DD-MON-RR' )
FROM DUAL
Results:
| TO_DATE('1-MAY-18','DD-MON-YYYY') | DATE'0018-05-01' | TO_DATE('1-MAY-18','DD-MON-RR') |
|-----------------------------------|----------------------|---------------------------------|
| 0018-04-29T00:00:00Z | 0018-04-29T00:00:00Z | 2018-05-01T00:00:00Z |
You will note that the YYYY format model and the numeric value 18 gives the year 18 AD and not 2018 AD. To fix this you need to either give the entire 4-digit year or use the RR format model.
The problem is you are not matching the format you are providing.
Year is provided as 18 and TO_DATE expects 2018.
Below should work fine:
select to_date('11-MAY-18', 'DD-MON-YY') from dual;
OR
select to_date('11-MAY-2018', 'DD-MON-YYYY') from dual;