Extract date from String column in sql - sql

I have a column as current_data and it has data which is of type string and data as {"settlement_date":"2018-07-21"}.
My question is that for each trade the settlement date will be diffrent and i want to extract the date i.e 2018-07-21 from the column current_data for each trade. I tried using select to_char(date_trunc(d.current_data,'YYYY-MM-DD')) as "Current_date" also i have tried the trim fuction but it does not work

It looks like JSON data. Since you're saying it's a text column internally you could use substring function to cut only the data you're looking for.
select substring(current_data from 21 for 10) from yourtable
You start taking the substring from 21 character and specify that it's length will be the next 10 characters.
With your sample data the result would be
db=# select substring('{"settlement_date":"2018-07-21"}' from 21 for 10);
substring
------------
2018-07-21
Beware though that this solution relies on length of the string and is designed for static input where the extracted substring is always within the same position.

Related

Concatening values in Snowflake

I'm trying to produce a unique value for a date so I can bucket table rows based on their date values. I tried doing this:
SELECT CONCAT(TO_VARCHAR(YEAR($1)), TO_VARCHAR(DAYOFYEAR($1)))
FROM VALUES ('2022-01-01'), ('1972-10-01')
I would expect this to produce the following results:
Column1
1
20221
2
19721
However, I'm actually receiving an error:
Function EXTRACT does not support VARCHAR(10) argument type
I have no idea what the term, EXTRACT, is, and this appears like it should work. What am I doing wrong here?
It requires a slight adjustment. As long as the date strings are YYYY-MM-DD there's no conversion required from the date strings:
SELECT CONCAT(year($1::date), DAYOFYEAR($1::date))
FROM VALUES ('2022-01-01'), ('1972-10-01')
However, the output is different. Since you're using DAYOFYEAR, the second row will have 275 for the day of year.
CONCAT(YEAR($1::DATE), DAYOFYEAR($1::DATE))
20221
1972275

Fetching min of current date from a lot of date strings in a single column

In a specific column I have grouped all the dates with timestamp sorted ASC as a string with ; seperator and that column can contain 1 - 50 date strings. From the date strings I have, i need to fetch the latest dates Min value.
Sample, (let's assume sysdaye date is 07/25/2019).
07/24/2019 12:02:44;
07/24/2019 12:03:56;
07/24/2019 10:02:44;
07/25/2019 12:02:44;
07/25/2019 12:03:56.
I am not certain the date value I wanted comes in the certain position and I know it can be done with RegEx. Can someone give me a RegEx for this or a suitable suggestion to do this any other way in Oracle SQL?
Assuming all your dates are sorted and have exactly one format, here's regex solution
select
dates,
regexp_substr(
dates,
concat(
regexp_substr(regexp_substr(dates, '(\d|\s|/|:|-)+$'), '(\d|/|:|-)+'),
'(\d|\s|/|:|-)+')
) as max_date_min_datetime
from
<table_name>

How would SQL treat this date format?

I had a coworker run a data pull for me. The query was essentially
SELECT a, b, c
FROM table
WHERE date >= 06/01/2018
The where clause being June 1, 2018. The query ran but the date filter was incorrect (not ‘2018-06-01’) How did the server interpret the date used? Was any filtering applied?
If you specified exactly as you have shown it, without quotes, then it would probably have:
1) Calculated 6 divided by 1 divided by 2018 (resulting in an integer zero)
2) Converted the dates in your database to an int to match the compare data type, and done a compare.
I expect this returned all your rows.
You can use this (datediff) function.
SELECT a, b, c
FROM table
WHERE datediff(dateVar, from_unixtime(unix_timestamp('2018/06/01','yyyy/MM/dd'),'yyyy-MM-dd')) >= 0
from_unixtime(,'yyyy-MM-dd') converts string to a string of given format, e.g. '2018-06-01'
Alternatively, these are functions which can help:
date_sub(,xxx) subtracts xxx days from the string, and returns a new
string in the same format.
unix_timestamp(string date,string pattern) converts a
string of a given pattern to unix time stamp, ) if fail.
Reference: How to change date format in hive?
This condition is:
WHERE date >= 06/01/2018
The last part is a numerical expression which I believe is interpreted as (06 / 01) / 2018. Depending on the database, this would either be 0 or about 0.00297, depending on whether your database does integer division.
Now the database has a bit of a conundrum. It has a date on one side and a number on the other. The rules of type conversion say to convert the date to a number. Depending on the database, this could be an error or a valid number -- which would be larger than 0.
The correct way to express this is:
WHERE date >= '2018-06-01'
or:
WHERE date >= DATE '2018-06-01'

Number format in SQL

I have a number for example 39.46
and i want it to convert in ,format i.e it should look like 39,46 in SQL
is there any function to convert decimal amount in , separated format ?
There is a NLS setting NLS_NUMERIC_CHARACTERS, where you can set "," as decimal separator and "." to separate thousands. They are typically automatically set when you set your locale. You obviously use an English locale.
See here.
This assumes you have actual numbers in your DB and not strings which look like numbers. For strings you may want to use sting conversion operations as described by Thomas G.
Below I demonstrate how to use the number format and the nls_numeric_characters parameter, both for a numeric input and a string input. Notice the d (or D) in the format model, it says "use whatever the appropriate decimal separator is."
SQL> select to_char(93.23, '999d99', 'nls_numeric_characters='',.''') from dual;
TO_CHAR
-------
93,23
1 row selected.
Elapsed: 00:00:00.14
SQL> select to_char(to_number('93.23'), '999d99', 'nls_numeric_characters='',.''')
from dual;
TO_CHAR
-------
93,23
1 row selected.

Why this Query is returning different results for different date formats?

I have a table named book_data with batch_dt as column name of type varchar in sql server.
when I pass the query
SELECT DISTINCT batch FROM book_data
it gives me the following results
batch_dt
-------------
2012-10-31
-------------
2012-11-01
-------------
2012-11-02
-------------
2012-11-03
-------------
.
.
.
Now what I am doing is getting the total count of records between two dates. Fairly a simple query.
SELECT COUNT(*) FROM book_data WHERE CONVERT(varchar(12),CONVERT(datetime,batch_dt),101) BETWEEN '11/02/2012' and '10/31/2012'
the result is
112
and just by changing the month from 02 to 2 the query gives me 218 results
SELECT COUNT(*) FROM book_data WHERE CONVERT(varchar(12),CONVERT(datetime,batch_dt),101) BETWEEN '11/2/2012' and '10/31/2012'
why this different behaviour?
Use CAST(batch_dt AS DATE) instead, and pass the date in a language neutral manner, in the format YYYYMMDD. This way it will be comared as a date not as a varchar:
SELECT COUNT(*)
FROM book_data
WHERE CAST(batch_dt AS DATE)
BETWEEN '20121102' and '20121130'
But, this is not safe, if there was any value in barch_dt in a wrong format, you will get a casting error. In this case you can add ISDATE(batch_dt) = 1 to ensure that it is a valid data time. But it is better to make this column of datatype DateTime.
Another thing to note: is that BETWEEN is asymmetric in SQL Server, meaning that BETWEEN '11/02/2012' and '10/31/2012' is evaluated as:
DATE >= '11/02/2012'
AND
DATE <= '10/31/2012'
which will never be true, the reason it works for you is that the dates were be compared as strings not as a dates. But you have to keep it like BETWEEN the small value and the biggest value.
You compare string with BETWEEN. If you do so you need to make sure that you compare in the correct order => YYYYMMDD MM:SS would be a correct order.
If you can, add columns with type datetime and store real date time values in your database. If you can not do that you can split up the values and build a date value yourself. This is much slower then just use a CONVERT() or CAST() but you can make sure that it works even with wrong date-strings.
You can use PATINDEX(),LEFT(),RIGHT() keywords to get the values you need or you use a split() function (you can find many version google it, e.g. https://codereview.stackexchange.com/questions/15125/sql-server-split-function-optimized). If you use the split function, then split by / and then get year, month, day from the positions.
But best would be still to have correct datetime values stored in your db.
You get this different behavior because you don't compare the dates but the strings/varchars.
For a Date (or DateTime), 10/2/2012 is the same as 10/02/2012.
But for string, these values are (of course) different. It's just as if you'd compare 'abcd' with 'ab0cd'
SELECT COUNT(*)
FROM book_data
WHERE CONVERT(DATETIME,batch_dt,101) BETWEEN '11/2/2012' and '10/31/2012'
This would be more appropriate