subtracting two years with to_char and to_number - sql

I need to subtract two dates. First I convert the date field to years using to_char, then convert to a number using to_number. However I get an error in the query when subtracting two years:
to_char((order date),'yyyy')
to_char((beginning of the year),'yyyy')
I tried converting to a number using
to_number(to_char((order date),'yyyy'),'9999')
to_number(to_char((beginning of the year),'yyyy'),'9999')

Use extract; it is simpler than what you're doing:
select extract(year from order_date) - extract(year from trunc(sysdate, 'yyyy')) as result
from some_table

You can use the EXTRACT function:
EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM order_date)
Or, if you want to get the actual difference and measure full years (accounting for months and not just years), then you can use MONTHS_BETWEEN and divide by 12 and round down:
FLOOR(MONTHS_BETWEEN(TRUNC(SYSDATE, 'YYYY'), order_date) / 12)

Related

how can I get the range of the time is last month but the time is a number data type?

Regarding to the previous question I have asked, i learnt that how to get the last month data in sql, here is my code:
EXTRACT(month FROM CURRENT_DATE)-1 = EXTRACT(month FROM LOG_DTM) and
EXTRACT(year FROM CU RRENT_DATE) = EXTRACT(year FROM LOG_DTM)
However, if the data type of LOG_DTM is changed into a number, not a time. So now LOG_DTM is the date and LOG_DTM_ID is a number which is based on the LOG_DTM
For example,
if the date is 2022-09-30, then LOG_DTM = '2022-09-30' but LOG_DTM_ID is a serious of number 20220930. My code isn't working anymore.
I try to do it add to_number(), but it seems doesn't work.
any direciton and ideas? Thank you guys
if the data type of LOG_DTM is changed into a number, ...
... then convert it to a valid DATE datatype value (use to_date, not to_number to do that; of course, with appropriate format model):
extract(month from current_date) - 1 = extract(month from to_date(log_dtm, 'yyyymmdd'))
In order to convert NUMBER to DATE you can use TO_DATE function:
EXTRACT(month FROM CURRENT_DATE)-1 = EXTRACT(month FROM to_date(LOG_DTM,'yyyy-mm-dd')) and
EXTRACT(year FROM CURRENT_DATE) = EXTRACT(year FROM to_date(LOG_DTM,'yyyy-mm-dd'))

How to easily get year and month with leading zero in BigQuery?

I have a snapshot date in the following format: 2021-06-28 and I would like to have it like that: 202106. So the first four digits is year and next two is the month with leading zero. I tried this code:
concat(extract(year from snapshot_date), extract(month from snapshot_date))
but I have in return: 20216, without leading zero. How can I easily get it without CASE statement?
Try format_date:
select format_date("%Y%m", snapshot_date)
from mytable
Assuming snapshot_date is of date data type - you can use recently introduced Format clause for CAST as in below example
select cast(snapshot_date as string format 'YYYYMM')
from `project.dataset.table`
if "snapshot_date" is in date format, then this should work
select to_char(snapshot_date, 'yyyymm') from table_name
As a note, you can return the value as a number and just use multiplication:
(extract(year from snapshot_date) * 100 + extract(month from snapshot_date)) as yyyymm

adding years getting invalid number error in case statement only - ORA-01722

Forgive me as I am new to this. I am trying to add a year to a date in a query. The year to be added is based on the month/day in the database. If the date is prior to November 1st then the year will be 2017 if it is after November 1st then it will be 2018. I have tried this a few ways (see below) and can get the years added in a query but when I put them in a case statement I get the 'Invalid Number' error.
Using to_char on the date:
CASE
WHEN to_char(au.creat_ts, 'MMDD') >= to_char('11/01/2018', 'MMDD') THEN
to_char(to_date( '2017'||to_char(au.creat_ts,'MMDDHH24MISS'),
'YYYYMMDDHH24MISS' ), 'MM/DD/YYYY')
ELSE
to_char(to_date( '2018'||to_char(au.creat_ts,'MMDDHH24MISS'), 'YYYYMMDDHH24MISS' ), 'MM/DD/YYYY')
END cmpltn_dt,
Adding Months:
CASE
WHEN to_char(au.creat_ts, 'MMDD') >= to_char('11/01/2018', 'MMDD') THEN
trunc(add_months(au.creat_ts,
floor(months_between(SYSDATE, au.creat_ts) / 12) * 12)) --calcx --add years
ELSE
trunc(add_months(au.creat_ts,
(floor(months_between(SYSDATE, au.creat_ts) / 12) - 1) * 12))
END calcx,
These run in select from dual statements with no error. Any ideas? Thanks so much in advance.
If AU.CREAT_TS is DATE, this works OK (meaning: it doesn't fail):
SQL> with au (creat_ts) as
2 (select date '2018-12-05' from dual
3 )
4 select
5 CASE WHEN to_char(au.creat_ts, 'MMDD') >= to_char(to_date('11/01/2018', 'dd/mm/yyyy'), 'MMDD') THEN
6 trunc(add_months(au.creat_ts, floor(months_between(SYSDATE, au.creat_ts) / 12) * 12))
7 ELSE trunc(add_months(au.creat_ts, (floor(months_between(SYSDATE, au.creat_ts) / 12) - 1) * 12))
8 END calcx
9 from au
10 ;
CALCX
-------------------
05.12.2018 00:00:00
SQL>
Note the difference: you used
CASE WHEN to_char(au.creat_ts, 'MMDD') >= to_char('11/01/2018', 'MMDD') THEN
and it raises the error because '11/01/2018' is a string; it is not a date. If you want to use a date, you have to tell Oracle so. How? See my working example.
The errors are coming from the two appearances of this clause:
to_char('11/01/2018', 'MMDD')
You're passing a string as the first argument (not a date), and Oracle defaults to trying to convert that string to a number - which throws the error you see.
You either need to pass in an actual date, by explicitly converting the string:
to_char(to_date('11/01/2018', 'MM/DD/YYYY', 'MMDD')
or with an ANSI literal:
to_char(date '2018-11-01', 'MMDD')
or if it's really a fixed value don't convert it at all, just do:
'1101'
or if you are being passed that streing from elsewhere - and you're sure about the format, of course - us substr() to extract the bits you need without trying to bounce it through a date.
Incidentally, converting values to and from dates and concatenating bits of strings together looks a bit messy and error-prone. And if that fixed date is always the first of a month, you could modify your case expression to only look at the month, e.g. via extract().

Dateadd and Datediff function in oracle

I want to use Oracle but DATEDIFF and DATEADD function doesn't work in Oracle DB.
How to write below mentioned code in Oracle?
datediff('QUARTER', pr.StartDate, SYSDATE)
datediff('MONTH', pr.StartDate, SYSDATE)
The best thing to do in this case is to use Oracle's MONTHS_BETWEEN() function.
Instead of:
datediff('QUARTER', pr.StartDate, SYSDATE)
you would use:
MONTHS_BETWEEN(pr.startdate, SYSDATE) / 3
and instead of:
datediff('MONTH', pr.StartDate, SYSDATE)
you would use:
MONTHS_BETWEEN(pr.startdate, SYSDATE)
Keep in mind that MONTHS_BETWEEN() will return fractions of months, so use TRUNC() or ROUND() if you need an integer number.
Of course, if you need days instead of months, you can simply subtract one date from another, e.g., SYSDATE - pr.startdate or vice-versa.
If you need to add days to a date, you can simply to this:
pr.startdate + 1 -- where 1 is the number of days
And if you need to add or subtract months, use the ADD_MONTHS() function - unlike INTERVALs this function is safe to use in leap years.
Hope this helps.
These do not have simple exact equivalents because of the semantics of datediff(). It counts the number of "boundaries" between two date/times.
I believe these are semantically equivalent:
trunc(months_between(trunc(pr.StartDate, 'Q'), trunc(sysdate, 'Q')) / 3)
months_between(trunc(pr.StartDate, 'MONTH'), trunc(sysdate, 'MONTH'))
Because of the truncation to the first day of the quarter/month, these should not be returning fractions.

Oracle SQL - Using SysDate to create a specific date

I need to automate a report that will always the first day of the current month and year in the WHERE caluses.
"YYYY-MM-01"
I am trying to achieve the following but sadly, I can't get anything to work using To_Char/ To_Date/SysDate.
to_date(SYSDATE('YYYY-MM') + '-01', 'yyyy-mm-dd')
Thank you
To get the first day of the current month (as a DATE), simply:
trunc(sysdate,'MON')
or, formatted:
to_char(trunc(sysdate,'MON'),'yyyy-mm-dd')
The string concatenation operator in Oracle is ||, not +. And SYSDATE is a constant not a function:
to_date(to_char(SYSDATE, 'YYYY-MM') || '-01', 'yyyy-mm-dd')
By the way, you can also do this calculation as:
trunc(sysdate - extract(day from sysdate) + 1)
That is, subtract the day of the month and add one. That way, you don't have to mess with fiddly date/character formats.