Timestamps and Intervals: NUMTOYMINTERVAL SYSTDATE CALCULATION SQL QUERY - sql

I am working on a homework problem, I'm close but need some help with a data conversion I think. Or sysdate - start_date calculation
The question is:
Using the EX schema, write a SELECT statement that retrieves the date_id and start_date from the Date_Sample table (format below), followed by a column named Years_and_Months_Since_Start that uses an interval function to retrieve the number of years and months that have elapsed between the start_date and the sysdate. (Your values will vary based on the date you do this lab.) Display only the records with start dates having the month and day equal to Feb 28 (of any year).
DATE_ID START_DATE YEARS_AND_MONTHS_SINCE_START
2 Sunday , February 28, 1999 13-8
4 Monday , February 28, 2005 7-8
5 Tuesday , February 28, 2006 6-8
Our EX schema that refers to this question is simply a Date_Sample Table with two columns:
DATE_ID NUMBER NOT Null
START_DATE DATE
I Have written this code:
SELECT date_id, TO_CHAR(start_date, 'Day, MONTH DD, YYYY') AS start_date ,
NUMTOYMINTERVAL((SYSDATE - start_date), 'YEAR') AS years_and_months_since_start
FROM date_sample
WHERE TO_CHAR(start_date, 'MM/DD') = '02/28';
But my Years and months since start column is not working properly. It's getting very high numbers for years and months when the date calculated is from 1999-ish. ie, it should be 13-8 and I'm getting 5027-2 so I know it's not correct. I used NUMTOYMINTERVAL, which should be correct, but don't think the sysdate-start_date is working. Data Type for start_date is simply date. I tried ROUND but maybe need some help to get it right.
Something is wrong with my calculation and trying to figure out how to get the correct interval there. Not sure if I have provided enough information to everyone but I will let you know if I figure it out before you do.
It's a question from Murach's Oracle and SQL/PL book, chapter 17 if anyone else is trying to learn that chapter. Page 559.

you'll want MONTHS_BETWEEN in that numtoyminterval as the product of subtracting two date variables gives the answer in days which isn't usable to you and the reason its so high is you've told Oracle the answer was in years! Also use the fm modifier on the to_char to prevent excess whitespace.
select date_id,
to_char(start_date, 'fmDay, Month DD, YYYY') as start_date,
extract(year from numtoyminterval(months_between(trunc(sysdate), start_date), 'month') )
|| '-' ||
extract(month from numtoyminterval(months_between(trunc(sysdate), start_date), 'month') )
as years_and_months_since_start
from your_table
where to_char(start_date, 'MM/DD') = '02/28';

You can simplify the answer like this
SELECT date_id, start_date, numtoyminterval(months_between(sysdate, start_date), 'month') as "Years and Months Since Start"
FROM date_sample
WHERE EXTRACT (MONTH FROM start_date) = 2 AND EXTRACT (DAY FROM start_date) = 28;

Related

Snowflake SQL: Is there a way to select records between 2 years back and the current date?

I have seen a lot of questions similar to this but I have yet to see one that goes into detail of how to get records from two years back to today but include the start of the year two years back. Meaning I would like to create a function that will always give me results from January 1st two years back. For this year the results would come from 01-01-2020 to today’s date.
This is what I have so far, but in reality I am using it for a temporary table in my query.
SELECT *
FROM final
WHERE order_date BETWEEN DATEADD(‘year’, -2, current_date) AND current_date
You may use a combination of DATE_TRUNC and DATEADD to find January 1 of two years ago.
SELECT *
FROM final
WHERE order_date BETWEEN DATE_TRUNC('year', DATEADD('year', -2, current_date)) AND current_date;
What you had is close. Just truncate the the year.
You can see what happens in isolation:
select trunc('2021-03-14 08:24:12'::timestamp, 'YEAR');
-- Output: 2021-01-01 00:00:00.000
Adding to your SQL:
SELECT *
FROM final
WHERE order_date
BETWEEN trunc(DATEADD(‘year’, -2, current_date), 'YEAR') AND current_date
It is possible to construct arbitrary date using DATE_FROM_PARTS:
Creates a date from individual numeric components that represent the year, month, and day of the month.
DATE_FROM_PARTS( <year>, <month>, <day> )
For current_date:
SELECT DATE_FROM_PARTS(YEAR(current_date)-2,1,1);
-- 2020-01-01
Full query:
SELECT *
FROM final
WHERE order_date BETWEEN DATE_FROM_PARTS(YEAR(current_date)-2,1,1) AND current_date
This should be enough
where year(current_date)-year(order_date)<=2
But in case you have an order_date from the future
where year(current_date)-year(order_date)<=2 and order_date<=current_date

Combine with month and year column kept in different columns on Oracle

I keep the month and year information in different columns as numbers.
I want to go back 12 months on sysdate using these columns.
The table I used below as an example ,
Since we are in the 5th month now, I want to get the data up to the 6th month of last year.
versiyon table :
So as a result of the query ,
the following result should return.
First of all, I want to query by combining the year and month columns and going back one year from the current month as a date.
Convert the values to strings and concatenate and then use ADD_MONTHS(SYSDATE, -12) to get last year's date (which will get the correct date regardless of whether it is a leap year or not):
SELECT *
FROM versiyon
WHERE TO_CHAR(year, 'fm0000') || TO_CHAR(month, 'fm00')
>= TO_CHAR(ADD_MONTHS(SYSDATE, -12), 'YYYYMM')
db<>fiddle here
select *
from versiyon
where lpad(year, 4, '0') || lpad(month, 2, '0') >= to_number(to_char(sysdate - 365, 'yyyymm' ))
Here is a demo
As MT0 say it will not work for leap years... so you can check if it is leap year or not with case when then end clause and using mod(year, 4) to check. In this demo I have created a situation as it is 2020, to be exact like it is 29th of February 2020. where you can see what I am suggesting in action:
DEMO2
You can convert your year and month into an integer form of YYYYMM and compare:
SELECT *
FROM versiyon_table
WHERE (versiyon_table.year * 100) + versiyon_table.month > (EXTRACT(YEAR FROM SYSDATE) * 100) + EXTRACT(MONTH FROM SYSDATE)

Sorting SQL Query By Date Column

I'm working on a project with a db that contains a date column for patient visits in the format of %m-%d-yyyy and need to sort so that it only pulls the rows where that date is within the last two weeks. I've tried a few different functions of convert, to_date, and can't seem to get anything to work.
I'm still very new to SQL and I don't know if this is a special case because I'm working with an oracle db
Not the full code, because it has dozens of queries and multiple joins (would that affect the date syntax?) but this is the format I'm trying for...
create table "Visits"
insert into "Visits" (
'John Doe',
'5/24/2021',
'Story about the visit',
'More room for story if needed')
select
"User_Name",
"Visit_Date",
"Visit_Narrative",
"Visit_Narrative_Overflow"
from "Visits"
where "Visits"."Visit_Date" >= TRUNC(SYSDATE) - 14
I'm working on a project with a db that contains a date column for patient visits in the format of %m-%d-yyyy
No, you don't have it in the format mm.dd.yyyy. A DATE data type value is stored within the database as a binary value in 7-bytes (representing century, year-of-century, month, day, hour, minute and second) and this has no format.
need to sort so that it only pulls the rows where that date is within the last two weeks.
You want a WHERE filter:
If you want to have the values that happened in the last 14 days then TRUNCate the current date back to midnight and subtract 14 days:
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE) - INTERVAL '14' DAY
or
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE) - 14
(or subtract 13 if you want today and 13 days before today.)
If you want it after Monday of last week then TRUNCate to the start of the ISO Week (which is always a Monday) and subtract 7 days:
SELECT visit_date
FROM patient
WHERE visit_date >= TRUNC(SYSDATE, 'IW') - INTERVAL '7' DAY
I ended up figuring it out based on an answer from another forum (linked below);
it appears that my original to_date() was incomplete without a second and operator in my where clause. This code is working perfectly
select
"User_Name",
"Visit_Date",
"Visit_Narrative",
"Visit_Narrative_Overflow"
from "SQLUser"."Visits"
where "SQLUser"."Visits"."Visit_Date" >= to_date('5/10/2021', 'MM/DD/YYYY')
and "SQLUser"."Visits"."Visit_Date" < to_date('5/24/2021', 'MM/DD/YYYY')

ORA-01839: date not valid for month specified

The following query returns
select to_char( trunc(sysdate) - numtoyminterval(level - 1, 'month'), 'mon-yy') as month from dual connect by level <= 12
last 12 months according to today's date(i.e. 2-Jan-18).
Say if today's date is 29-DEC-17 it gives oracle sql error:
ORA-01839: date not valid for month specified
(since on subtracting there would be a date in the result as '29-FEB-17' which is not possible). So on specific dates this error would pop-up. How do you suggest to overcome this?
I prefer ADD_MONTHS (TRUNC of a date literal is stupid, but I left it as you'd have SYSDATE anyway, wouldn't you?):
SQL> select to_char(add_months(trunc(date '2017-12-29'), -level), 'dd-mon-yy',
2 'nls_Date_language = english') as month
3 from dual
4 connect by level <= 12;
MONTH
------------------
29-nov-17
29-oct-17
29-sep-17
29-aug-17
29-jul-17
29-jun-17
29-may-17
29-apr-17
29-mar-17
28-feb-17
29-jan-17
29-dec-16
12 rows selected.
SQL>
This behavior of INTERVAL YEAR TO MONTH is as documented, see Datetime/Interval Arithmetic
You should consider function ADD_MONTHS:
If date is the last day of the month or if the resulting month has
fewer days than the day component of date, then the result is the last
day of the resulting month. Otherwise, the result has the same day
component as date.
It depends on your requirements what you consider as "right". In fact "one month" does not have a fixed duration.

Sql daily comparison by month

I am writing a report for work which requires that I compare the amount of students dropped on a daily basis, what I mean is the report needs to show that on today the 5th of august X amounts of students dropped from the 1st to the 5th compared to X amount which dropped within the 1st to the 5th of July and so on for each Month of the year. Can anyone please help me by providing me with a query which I can use to have that info? thanks.
You want to compare the first number of days from a month. The following query gives you an example:
select yr, mon, count(*)
from (select extract(year from date) as yr, extract(month from date) as mon,
extract(day from date) as day
from t
) t
where day <= extract(day from now())
group by yr, mon
However, the exact syntax may depend on your database. For instance, the current date may be now(), getdate(), system_date or something else. Some databases don't support the extract, but most have a way to get the month and day of month.