INSERT INTO DELLL (
DATETIMEMY)
SELECT to_date(to_char(SU_MODIFYDATE, 'YYYY/MM/DD'),'YYYY/MM/DD') AS DATETIMEMY
FROM SER_TBLSERVICES WHERE SVE_SERVICEID=422
SU_MODIFYDATE = 01/18/2013
but after insertion in DELLL date (DATETIMEMY) format still same is still same
DATETIMEMY = 01/18/2013
you dont assign a format to a DATE. They are stored internally as a number and have no format. the format comes when you want to select the date. so in your case you should just do this:
first just insert the date as-is, do not try to convert it to a char and back again:
SQL> INSERT INTO DELLL (
2 DATETIMEMY) SELECT SU_MODIFYDATE
3 FROM SER_TBLSERVICES WHERE SVE_SERVICEID=422;
1 row created.
now to select it in a specific format, you can use TO_CHAR to format it.
SQL> select * from delll;
DATETIMEMY
----------
01/18/2013 <-- which isn't what you want to see, you wanted to see yyyy/mmm/dd. so...
SQL> select to_char(DATETIMEMY,'yyyy/mm/dd') DATETIMEMY from DELLL
2 /
DATETIMEMY
----------
2013/01/18
or, to apply to all selects in that session that have a date datatype, you can alter the default display format:
SQL> alter session set nls_date_format='yyyy/mm/dd';
Session altered.
SQL> select * from delll;
DATETIMEMY
----------
2013/01/18
The INSERT or SELECT in your example does not modify how a date is stored. Dates are formatted when you SELECT them, using your current connection format preferences/locale.
You are using TO_DATE, selecting that returned value is the same as with any other date, it will be formatted according to the locale.
DazzaL is right with his answer which discusses formatting, storage and retrieval of dates.
I would like to discuss what you are doing in your code.
Oracle stores dates upto precision of a seconds. In simple terms you can retrieve the date in MM/DD/YYYY HH24:MI:SS format.
By issuing to_date(to_char(SU_MODIFYDATE, 'YYYY/MM/DD'),'YYYY/MM/DD') you are actually truncating the date up to the day part. So when you try to retrieve this value, the HH24:MI:SS part will have 00:00:00 because you have truncated the date.
If you want all the details (from year, month, day to hour, minute and seconds) from SU_MODIFYDATE to be inserted into the column in DELLL, you should just use
INSERT INTO DELLL (
DATETIMEMY)
SELECT SU_MODIFYDATE AS DATETIMEMY
FROM SER_TBLSERVICES WHERE SVE_SERVICEID=422
This will ensure all parts of date in SU_MODIFYDATE column are inserted into the new column.
If you want to truncate the date, for example, upto the minute the use to_date(to_char(SU_MODIFYDATE, 'YYYY/MM/DD HH24:MI'),'YYYY/MM/DD HH24:MI')
Likewise, you can truncate dates from year part upto the second part as per your choice.
If you want to insert truncated dates then you should use the query you already have. If you want to insert dates with all their parts then avoid truncating by using to_char and to_date.
Related
I have test table where column sys_created_on(datatype is varchar(15)) is a datetime field and we receive two different date formats like below.
03-04-2022 12:49
2/28/2022 10:35
Expected Result is:
03-04-2022 12:49
02-28-2022 10:35
Could you please suggest if there is any way to convert all formats to one format instead..
any suggestions can be appreciated. Please suggest if datatype change can help anything here.
Thank you!!
The best thing to do here would be to just convert your text timestamp column to a bona fide timestamp column. You could achieve this using the TO_TIMESTAMP() function along with a CASE expression:
SELECT
ts,
CASE WHEN REGEXP_LIKE(ts, '\\d{1,2}-\\d{2}-\\d{4} \\d{1,2}:\\d{2}')
THEN TO_TIMESTAMP(ts, 'mm-dd-yyyy hh24:mi')
ELSE TO_TIMESTAMP(ts, 'mm/dd/yyyy hh24:mi') END AS ts_real
FROM yourTable;
Assuming you had a new timestamp column, you could populate it using the ts text column as follows:
UPDATE yourTable
SET ts_real = CASE WHEN REGEXP_LIKE(ts, '\\d{1,2}-\\d{2}-\\d{4} \\d{1,2}:\\d{2}')
THEN TO_TIMESTAMP(ts, 'mm-dd-yyyy hh24:mi')
ELSE TO_TIMESTAMP(ts, 'mm/dd/yyyy hh24:mi') END;
TRY_TO_DATE return null if it fails so you can just chain different formats together with COALESCE or NVL
SELECT column1,
TRY_TO_DATE(column1, 'dd-mm-yyyy hh:mi') as d1,
TRY_TO_DATE(column1, 'mm/dd/yyyy hh:mi') as d2
,nvl(d1,d2) as answer
FROM VALUES ('03-04-2022 12:49'),('2/28/2022 10:35');
gives:
COLUMN1
D1
D2
ANSWER
03-04-2022 12:49
2022-04-03
2022-04-03
2/28/2022 10:35
2022-02-28
2022-02-28
which can be merged as
,nvl(TRY_TO_DATE(column1, 'dd-mm-yyyy hh:mi'),TRY_TO_DATE(column1, 'mm/dd/yyyy hh:mi')) as answer
ah, didn't read well enough, to make them all the same, UPDATE but use the "local format" thus just a TO_CHAR
thus:
UPDATE table
SET sys_created_on = to_char(nvl(
TRY_TO_TIMESTAMP(sys_created_on , 'dd-mm-yyyy hh:mi'),
TRY_TO_TIMESTAMP(sys_created_on , 'mm/dd/yyyy hh:mi')
));
Replace the separator using replace():
update test_table
set sys_created_on = replace(sys_created_on,'/','-');
If you're also dealing with different day and month field order, look into regexp_replace() to swap their places:
update test_table
set sys_created_on = regexp_replace(sys_created_on,
'(.*)/(.*)/(.*)',
'\\2-\\1-\\3');
That's in case your 03-04-2022 is in format dd-mm-yyyy making it April 3rd, not March 4th. It's good to know what exact format you're dealing with. In extreme cases you might even need to make sure whether your hour field is 24-h or 12-h-based but missing an am/pm meridiem indicator.
As suggested by Tim's and Simeon's answers, a matching data type is always encouraged. It takes less space, queries faster, enables type-specific functions and maintains validity of data (varchar doesn't care if you get February 30th or 32nd day of month 13, at 25:60)
If you want to keep the cookie and eat it too, here's how you can add one virtual column where you'll always see a standardised version of your sys_created_on, and another one, which will always interpret it as a proper timestamp. This way you don't need to touch anything in how the table is populated, keep the original, unprocessed data, see how it gets standardised, and also benefit from a timestamp data type, while not using up any additional space:
alter table test_table
add column standardised_sys_created_on varchar(15)
as replace(sys_created_on,'/','-'),
add column timestamp_sys_created_on TIMESTAMP_NTZ
as coalesce(
try_to_date(sys_created_on, 'dd-mm-yyyy hh24:mi'),
try_to_date(sys_created_on, 'dd/mm/yyyy hh24:mi'));
To make it faster at the expense of materializing them, you can turn those virtual columns into generated/computed using default.
My table INV_STOCK_TIME with 4000 rows with unix epoch data in snowflake. That data needs to be converted to date. Here is sample data and the desired output should be in 2 columns as given below
STOCK_RAWTIME
1617772221333
1616217315003
1601376748863
STOCK_RAWTIME STOCK_DATE
1617772221333 2021-04-07
1616217315003 2021-03-20
1601376748863 2020-09-29
I could to convert value in column using either of the below command.
select to_char(to_timestamp_tz(1617772221333,3),'YYYY-MM-DD') from dual;
OR
SELECT to_char(dateadd('ms',timestamp_col,'1970-01-01'),'YYYY-MM-DD') from (select 1617772221333 as timestamp_col) as timetest;
I would like to pass the values of column1 STOCK_RAWTIME (unix epoch value)
to populate column2 STOCK_DATE. I'm unable to pass list of values to convert column1 records with below error
Format argument for function 'TO_TIMESTAMP_TZ' needs to be a string
I believe you can get this requirement with the following:
SELECT STOCK_RAWTIME as STOCK_RAWTIME, to_date(STOCK_RAWTIME)AS STOCK_DATE FROM (select STOCK_RAWTIME from INV_STOCK_TIME);
Resolved with this step in snowflake as to_date or to_timestamp works fine:
alter table inv_stock_time add column stock_date date;
update inv_stock_time set stock_date=to_date(STOCK_RAWTIME);
I am using the latest SQL Server. I have a table with a CreatedDate column. I need to write a Query that uses dates that are plus or minus 7 from the Date in CreatedDate. I have no clue how to go about this. My thought was this:
DECLARE #Date datetime
DECLARE #SevenBefore datetime
DECLARE #SevenAfter datetime
SET #Date = CreatedDate
SET #SevenBefore = DATEADD(day,-7,#Date)
SET #SevenAfter = DATEADD(day,7,#Date)
SELECT *
FROM <table>
WHERE <table> BETWEEN #SevenBefore AND #SevenAfter
The issue with this is that I cannot use "CreatedDate" as a SET #DATE because SQL gives an error "Invalid column name 'CreatedDate'"
Any help would be appreciated. I cannot list a date because every date in that column could be different.
Thanks
In this case, you need to stop thinking as a programmer would, and start thinking as a Database programmer would.
Lets work only with this central part of your query:
SELECT *
FROM <table>
WHERE <table> BETWEEN #SevenBefore AND #SevenAfter
Now, you say that the CreatedDate is a column in a table. For this example, I will assume that the CreatedDate is in a table other than the one in your example above. For this purpose, I will give two fake names to the tables. The table with the CreatedDate, I will call tblCreated, and the one from the query above I will call tblData.
Looking above, it's pretty obvious that you can't compare an entire table row to a date. There must be a field in that table that contains a date/time value. I will call this column TargetDate.
Given these assumptions, your query would look something like:
SELECT *
FROM tblCreated tc
INNER JOIN tblData td
ON td.TargetDate BETWEEN DATEADD(day, -7, tc.CreatedDate) and DATEADD(day, 7, tc.CreatedDate)
Looking at this, it is clear that you still need some other associations between the tables. Do you only want all data rows per customer based on the Created date, or perhaps only want Creations where some work was done on them as shown in the Data records, or ??. Without a fuller specification, we can't help with that, though.
I have a view where I Select about 100 rows to allow users to easily query data. In this data, I have a field that is sometimes a date and sometimes text. A date or text depends on type. I cast to a date value like so.
SELECT Cast(Value as Date) as column
from Table
Where type = 1
When you then try to run a query against this column, you get a Conversion failed when converting date and/or time from character string. Here is the query.
SELECT Column
From View
WHERE Column BETWEEN '01/01/2015' AND '12/31/2015'
I have another field that is a date and if I replace it in this query, the query works. Likewise the data from the whole table will load. Any ideas are appreciated. Thanks
Basically, I need this Query to work and not give me the error described above.
select cast(value as date)
from Value
where type = 1
and cast(value as date) between '01/01/2015' and '12/31/2015'
My guess is that you have entries in that column that cannot be converted to datetime. You may be able to find them by running
Select * from table where isdate(value) = 0
I've created a virtual table in SQL Server that has 28 days from the current date and each date has rows for time that range from 12-10 pm incremented by 15 min and another value to indicate that it's turned on/off for availability, so it would be something like this:
date time onoff
-------------------------------------------------
2015-04-08 12:00 1
2015-04-08 12:15 1
....continue until 22:00 then start next day
2015-04-09 12:00 1
..... continue for 28 days
I'd like to update the availability based on a query from another table which would return the date, start and end time...
So far I came up with this
update table1
set onoff = 0
where tbl1date in (select tbl2date from table2 where userid = 1)
The problem I'm having is adding in the between certain hours part of the equation and I'm not sure how to do something like this in SQL or how to even search for the answer based on not being able to word it properly...
Can someone help or point me in the right direction?
use a DATETIME, don't use separate DATE and TIME fields.
I think you should take a look at DATEDIFF (https://technet.microsoft.com/pl-pl/library/ms189794(v=sql.110).aspx) function.
Your where query could look like this:
update table1 set onoff = 0
where
DATEDIFF(minute, <MIN_RANGE>, tbl1date) >= 0 and
DATEDIFF(minute, tbl1date, <MAX_RANGE>) >= 0
How you calculate MIN_RANGE and MAX_RANGE depends on your table2 structure.
As suggested, if you have control over the structure, use datetime fields as they are easier to do the comparisons on. I'm going to assume you don't have control over the structure.
In order to compare the datetimes you need to create them from your separate date and times. You can either parse the time field for the hours and minutes and use DATEADD to add the appropriate offsets to the date, or you can use CONVERT to interpret a date time string as a date. Something like
CONVERT(datetime, SUBSTRING(CONVERT(varchar, tbl1date, 121), 1, 10) + ' ' + tbl1time, 121)
What this does is to convert the date to odbc cannonical format and throwaway the time part as it takes only the first 10 characters. Then it appends the time and interprets the whole string as a odbc cannonical datetime string. That format is yyyy-mm-dd hh:mi:ss.mmm. The hours are based on 24 hours. So if your times are in AM/PM format you're going to have to convert them.
If your other table has separate date and times you'd use a similar expression to combine them.
Once you have the datetimes you can do something like this
UPDATE table1
SET onoff = 0
WHERE <expression above> BETWEEN (SELECT min_value FROM table2) AND (SELECT max_value FROM table2)