SQL convert into Data field to compare with current date - sql

I have one field in a Firebird DB containing dates like this
27.09.2014
untill no I compared it to the current date with
substring(100+extract(day from current_date) from 2 for 2)
|| '.' ||
substring(100+extract(month from current_date) from 2 for 2)
|| '.' ||
extract(year from current_date)
= date_field_to_compare
But now i need to keep out the greater dates and this turns out to be impossible in this case, since its not handling native dates but numbers.
So I actually need to do the opposite, to convert the
27.09.2014
into A SQL date.
Like
SELECT date_field_to_compare FROM db WHERE
date_field_to_compare < CURRENT_DATE
But how can I Convert this DB Date field into a SQL understandable date?

You shouldn't store dates in (VAR)CHAR fields, store them in a DATE. It will solve these types of problems, and make things like selecting, sorting etc a lot easier.
That said Firebird supports a number of date conversions from string, and dd.MM.yyyy is one of them:
SELECT CAST('27.09.2014' AS DATE) FROM RDB$DATABASE
Or:
SELECT date_field_to_compare
FROM db
WHERE CAST(date_field_to_compare AS DATE) < CURRENT_DATE
Related: https://stackoverflow.com/a/23857635/466862

Related

SQL Oracle table blank when trying to query date data stored as varchar

I have a column called received_dt_key in Varchar in the format DD-MM-YYYY (e.g. 30-07-2021).
I would like to select all from the table for dates between 31-12-2021 and 01-01-2022. I have tried version of the below query and a blank table is the output.
SELECT *
FROM SD_BDAY
WHERE to_char(to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY')) > to_char(to_date('31-12-2021', 'DD-MM-YYYY'))
and to_char(to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY')) < to_char(to_date('01-01-2022', 'DD-MM-YYYY'));
Don't compare dates as strings. Compare them as dates:
SELECT *
FROM SD_BDAY
WHERE to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') > to_date('31-12-2021', 'DD-MM-YYYY')
and to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') < to_date('01-01-2022', 'DD-MM-YYYY');
If you try to compare them as strings then you are looking for string that is greater than '31-12-2021' and less than '01-01-2022' and the string comparison will look at the first character and see if it can find a match which is greater than '3' and less than '0'; there can never be such a match so it is quite correct that when comparing as strings nothing is returned.
As pointed out by #AlexPoole in comments, even if you compare the values as dates (rather than strings) you will still never return a result as finding values that are greater than DATE '2021-12-31' and less than DATE '2022-01-01' would return all dates from 2021-12-31 00:00:01 to 2021-12-31 23:59:59; however, your values will always be converted with a midnight time component and, therefore, will never fall into that range so cannot be returned.
What you probably want is to use >= rather than > and then it would match values on 2021-12-31.
The best thing would be to store calendar dates in date data type column. Why else do you think Oracle designed that data type? This way you may create normal indexes on data data type columns, or, if needed, partition the table by that date column.
Still, if you insist in having the calendar dates stored like that, I think the below should work:
SELECT *
FROM SD_BDAY
WHERE to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') >
to_date('31-12-2021', 'DD-MM-YYYY')
and to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') <
to_date('01-01-2022', 'DD-MM-YYYY');
Thus you compare calandar dates with calendar dates, not varchar with varchar, as it results from the code you have written.
And what if in the varchar2 column there is somethibng that can't be converted to date? That is why it is best to use the date data type.

fetch records between 'current date ' and next 5 days(future date) in oracle

Select * from dual where between to_date(date,'YYYY-MM-DD') = '2020-10-01'
and to_date(date,'YYYY-MM-DD') + 5
this is correct way to write query?
1.format of date is varchar2
2.required data between current date and next 5 days
3.first needs to convert into date format.
4. next 5 should be +5 in current day
You probably meant to write:
where to_date(mydate, 'yyyy-mm-dd') between trunc(sysdate)
and trunc(sysdate) + 5
Rationale:
date is a reserved word; I assume that's not the actual name of your column, so I used something else; if that's the real name, then you need to surround it with double quotes ("date", or "DATE", or else, depending on how it was initially defined)
mydate is a string so you need to turn it to a date: for this, you can use to_date()
you then compare it to the current date, without the time portion : trunc(sysdate), and the same date 5 days later
Note, however, that this would be more efficiently expressed as follows:
where mydate between to_char(trunc(sysdate), 'yyyy-mm-dd')
and to_char(trunc(sysdate + 5), 'yyyy-mm-dd')
This avoids the date conversion on the string column, and instead converts the interval bounds. Here, string comparison is possible, because the format of the string you are storing allows it (it it was stored as dd-mm-yyyy' for example, this would not be possible).
Let me, however, strongly suggest to store your dates as dates rather than string. You should always use the proper datatype, for many reason, such as data integrity and efficency.

Format int as date in presto SQL

I have an integer date column "date_created" storing values like...
20180527, 20191205, 20200208
And am wondering what the best way to parse as a date is so I could do something like this in a query...
select * from table where formatted(date_created) > formatted(date_created) - 90
(to return everything within the last 90 days)
I've found some similar examples that convert from date ints representing seconds or milliseconds, but none where the columns are essentially date strings stored as integers.
Appreciate any thoughts on the best way to achieve this
And am wondering what the best way to parse as a date is so I could do something like this in a query...
You can convert "date as a number" (eg. 20180527 for May 27, 2018) using the following:
cast to varchar
parse_datetime with appropriate format
cast to date (since parse_datetime returns a timestamp)
Example:
presto> SELECT CAST(parse_datetime(CAST(20180527 AS varchar), 'yyyyMMdd') AS date);
_col0
------------
2018-05-27
However, this is not necessarily the best way to query your data. By adapting your search conditions to the format of your data (and not vice versa), you can potentially benefit from predicate push down and partition pruning. See #GordonLinoff answer for information how to do this.
You can do the comparison in the world of integers or of dates. You might as well convert the current date minus 90 days to a number:
select t.*
from t
where date_created >= cast(date_format(current_date - interval '90 day',
'%Y%m%d'
) as int
);
the below query is index friendly for any database since it does not use function on indexed column
select * from table where date_created > timestamp (formatted(date) - 90)
In addition, suppose we have date in format 20211011_1234 and we want one month older date and want back the original format, we can use the following formatting to convert date to int and vice versa.
select cast(date_format(
CAST(parse_datetime(cast(
split_part('20211011_1234', '_', 1) as varchar), 'yyyyMMdd')
AS date) - interval '30' day ,'%Y%m%d') as int) as column_name

How to compare 2 converted dates in sql

I'm trying to exclude results in my query that start in the same month between two columns. For example, I need to exclude benefits1 that start in the same month as benefits2. Format for benefit1_start_date and benefit2_start_date is: YYYYMMDD.
This is what I have so far:
where (benefit1_start_date = (to_char(sysdate, 'YYYYMM') || '0122')) <>
(benefit2_start_date = (to_char(sysdate, 'YYYYMM') || '0122'));
If anyone could put me in the right direction, I'd greatly appreciate it!
Convert your numeric dates to text, and then compare the year and month substrings:
WHERE
SUBSTR(TO_CHAR(benefits1_start_date), 1, 6) <> SUBSTR(TO_CHAR(benefits2_start_date), 1, 6)
Note that storing your dates as numbers like this is atypical, and you might want to consider storing them as dates. If you don't have a day component, you could just use the first as a placeholder.
As I understand it, you want to eliminate records where your 2 columns benefits1_start_date and benefits2_start_date are in the same month, and both have a format of YYYYMMDD.
Are they stored as strings? If so, all you need to do is compare the first 6 characters (if you need to consider yr + month), or just the 5+6th characters if you want to check just the month without the year.
Year + Month:
SUBSTR(benefits1_start_date,1,6) <> SUBSTR(benefits2_start_date,1,6)
Just month:
SUBSTR(benefits1_start_date,5,2) <> SUBSTR(benefits2_start_date,5,2)
If they're not stored as strings but as dates, then you can TRUNC the date to month and compare (for yr + month), or convert the date to MM string via to_char and compare if you just want to check the month.
Hope this helps.
I suggest you to use BETWEEN clause. Converting LEFT side operand to string by function and then making comparison can have severe performance impacts.
if you convert indexed table.dateColumn to string by to_char(table.dateColumn), oracle cannot use defined index on column anymore.
Your desired query:
where to_char(benefit1_start_date, 'YYYYMM') != to_char(benefit2_start_date, 'YYYYMM')
but
select * from table1
where months_between(benefit1_start_date, benefit2_start_date) not between -1 and 1
would be what you are looking for. (no performance impact)

Select Varchar as Date

I want to select a varchar field as a date field
For example a field has this value "30.12.2011 21:15:03"
and when i select this
select DATE from TABLE where DATE = '30.12.2011'
i get no result.
You ask about getting the date part of a timestamp field, but what your question is actually about is filtering on the date of a timestamp field. There is a much simpler method of accomplishing that: you can use the knowledge that all the possible timestamps on a specific date won't have any timestamps for different dates between them.
select DATE
from TABLE
where DATE >= '30.12.2011' and DATE < '31.12.2011'
Your edit explains that you haven't got a timestamp field at all. Nevertheless, a similar approach may still work:
select DATE
from TABLE
where DATE LIKE '30.12.2011 %'
Or the Firebird-specific
select DATE
from TABLE
where DATE starting with '30.12.2011 '
Assuming the field is a date field, use the DATE introducer combined with yyyy-mm-dd (or TIMESTAMP with time as well).
So use:
select datefield from sometable where datefield = DATE '2011-12-30'
Technically you can leave off the introducer, but it is 'correcter' in the light of the SQL standard.
Assuming a TIMESTAMP field, you won't get results unless the timestamp is (always) at 00:00:00.0000 (in which case it should have been a DATE instead).
For the comparison to work, you need to use either BETWEEN, eg:
select timestampfield from sometable
where timestampfield BETWEEN '2011-12-30 00:00:00.0000' AND '2011-12-30 23:59:59.9999'
or truncate the timestamp to a date (this may adversely effect performance if the timestamp is indexed, because then the index can no longer be used), eg:
select timestampfield from sometable
where CAST(timestampfield AS DATE) = '2011-12-30'
If the date is stored in a VARCHAR field (which in itself is a bad idea), there are several solutions, first is to handle it as date manipulation:
select varcharfield from sometable
where CAST(CAST(varcharfield AS TIMESTAMP) AS DATE) = '2011-12-30'
The double cast is required if you have a time-component in VARCHARFIELD as well. This assumes dates in the supported format listed below. If you use BETWEEN as above, you can use a single cast to timestamp)
The other solution (as suggested by hvd) is to treat it purely as string manipulation, for example:
select varcharfield from sometable
where varcharfield STARTING WITH '30.12.2011'
This has its own set of problems if you want to select ranges. Bottomline: use a real TIMESTAMP field!
Note that Firebird supports multiple formats:
yyyy-mm-dd, eg 2014-05-25 (ISO-8601 format, probably best to use as it reduces confusion)
dd.mm.yyyy, eg 25.05.2014
mm/dd/yyyy, eg 05/25/2014
mm-dd-yyyy, eg 05-25-2014
dd mmm yyyy, eg 25 MAY 2014 (+ variations with a -, . or / as separator)
mmm dd yyyy, eg MAY 25 2014 (+ variations with a -, . or / as separator)
select DATE from TABLE where cast(DATE as date) = '30.12.2011'
Date field is a timestamp
Here is the answere to my question:
CAST
(
SUBSTRING
(field FROM 1 FOR 2)
||'.'||
SUBSTRING
(field FROM 4 FOR 2)
||'.'||
SUBSTRING
(field FFROM 7 FOR 4)
AS DATE)
This took me 5 hours to find this out, maybe there should be a "-" instead of "." but it works.