Oracle : Selecting date by month with where clause - sql

I came across a problem that in selecting the date for current desired month and year. I tried the 2 statements shown below but failed to execute the query
select to_char(sysdate, 'Month') from income
select * from income where to_char(sysdate,month) = 'feb'
Update
But after researching and learning more in depth on oracle docs website. What i came out with is to use "between" clause. Specifying the first day and last day of the month . Doing so, it will execute the desired month/year
For an example
SELECT column_name
FROM table_name where column_name = (Your own value) AND
column_date >= to_date('01/02/2012', 'dd/mm/yyyy')
and column_date < to_date('01/03/2012', 'dd/mm/yyyy')
I hope this help :)

Are you after something like:
select *
from income
where <date_column> >= to_date('01/05/2019', 'dd/mm/yyyy')
and <date_column> < to_date('01/06/2019', 'dd/mm/yyyy')
(replacing <date_column> with the name of the date column in your income table that you want to filter on)?

I think you can use the following query:
select *
from income
where to_char(<date_column>,'MON-RRRR') = 'MAY-2019';

If you want to pass in a string like 'May 2012', then I would recommend:
select i.*
from income i
where i.datecol >= to_date('May 2012', 'Mon YYYY') and
i.datecol < to_date('May 2012', 'Mon YYYY') + interval '1' month;
That said, I think your application should turn the string value into a date range and you should use that range in your query:
select i.*
from income i
where i.datecol >= :datestart
i.datecol < :dateend + interval '1 day';
I strong encourage you to avoid between with dates, particularly in Oracle. The date data type has a built-in time component, and that can throw off the comparisons.

Related

SQL to check current date with column of type string which stores date in the format MMDD is not 120 days old

Oracle table in my application has a column with name "transaction_date" of type string. It stores date in the format MMDD, where MM = month and DD = day.
Please help me to write a SQL statement which will compare the transaction_date column with the current system date, if transaction_date is less than or equal to 120 days, then fetch the records from the table.
The problem I am facing is, transaction_date in db does not have year just month and day as a string value, so how to check if that value is not more than 120 days, that check should work if value in column is of previous year. For example, SQL should work for the scenario where current system date is lets say 01 feb 2018, and the transaction_date column in table has value "1225" (25th dec of previous year).
As a general disclaimer, your current table design is sub optimal, because a) you are storing dates as text, and b) you are not even storing the year for each date. From what you wrote, it looks like you want to consider all data as having occurred within the last year, from the current date.
One trick we can try here is to compare the MMDD text for each record in your table against TO_CHAR(SYSDATE, 'MMDD'), using the following logic:
If the MMDD is less than or equal to today, then it gets assigned to current year (2018 as of the time of writing this answer)
If the MMDD is greater than today, then it gets assigned to previous year (2017).
Then, we may build dates for each record using the appropriate year and check if it is within 120 days of SYSDATE.
WITH yourTable AS (
SELECT '0101' AS date_col FROM dual UNION ALL
SELECT '1001' FROM dual UNION ALL
SELECT '1027' FROM dual UNION ALL
SELECT '1215' FROM dual
)
SELECT
date_col
FROM yourTable
WHERE
(date_col <= TO_CHAR(SYSDATE, 'MMDD') AND
TO_DATE(date_col || TO_CHAR(SYSDATE, 'YYYY'), 'MMDDYYYY') >= SYSDATE - 120) OR
(date_col > TO_CHAR(SYSDATE, 'MMDD') AND
TO_DATE(date_col ||
TO_CHAR(TRUNC(ADD_MONTHS(SYSDATE, -12), 'YEAR'), 'YYYY'), 'MMDDYYYY') >=
SYSDATE - 120);
Demo

How to get Year and Month of a DATE using Oracle

How can I get the year and month of a date in the where clause using Oracle.
I used to be working with SQL server and it was as simple as YEAR(FIELDNAME) and MONTH(FIELDNAME).
I have tried the following:
SELECT *
FROM myschema.mytablename
WHERE EXTRACT(YEAR FROM myDATE) = 2017
however it gives ORA-30076 Error
Have you tried EXTRACT()?
SELECT EXTRACT(YEAR FROM DATE '2017-12-01') FROM DUAL;
2017
SELECT EXTRACT(MONTH FROM DATE '2017-12-01') FROM DUAL;
12
I tried this in sql fiddle with 11g and it works in WHERE clause too.
http://sqlfiddle.com/#!4/fb2b09/2
SELECT *
FROM myschema.mytablename
WHERE TO_CHAR(myDATE, 'YYYY') = '2017';
Explicitly convert year part of DATE into CHAR and compare it with literal.
For year and month comparison:
SELECT *
FROM myschema.mytablename
WHERE TO_CHAR(myDATE, 'YYYY') = '2017' AND TO_CHAR(myDate, 'MM') = '07';
Your query should work, but a better alternative would be
SELECT *
FROM YOUR_TABLE
WHERE MY_DATE BETWEEN TO_DATE('01-JAN-2017', 'DD-MON-YYYY')
AND TO_DATE('01-JAN-2018', 'DD-MON-YYYY') - INTERVAL '1' SECOND
Best of luck.
I did this with the function EXTRACT() and it works good for me.
I'm gonna share the query code here:
SELECT extract(YEAR from s.CREATE_DATE) as YEAR, extract(MONTH from s.CREATE_DATE) as MONTH, s.SALES_PERSON_GID, COUNT(s.SALES_ORDER_ID) as "TOTAL ORDERS" FROM SALES_ORDERS s, SALES_ORDER_STATUS ss WHERE s.SALES_ORDER_ID = ss.SALES_ORDER_ID and ss.STATUS_TYPE_ID = 'SALE ORDER STATUS' and ss.STATUS_VALUE_GID = 'SALE ORDER STATUS_DELIVERED' GROUP BY s.SALES_PERSON_GID,s.CREATE_DATE

Oracle SQl Dev, how to calc num of weekdays between 2 dates

Does anyone know how can I calculate the number of weekdays between two date fields? I'm using oracle sql developer. I need to find the average of weekdays between multiple start and end dates. So I need to get the count of days for each record so I can average them out. Is this something that can be done as one line in the SELECT part of my query?
This answer is similar to Nicholas's, which isn't a surprise because you need a subquery with a CONNECT BY to spin out a list of dates. The dates can then be counted while checking for the day of the week. The difference here is that it shows how to get the weekday count value on each line of the results:
SELECT
FromDate,
ThruDate,
(SELECT COUNT(*)
FROM DUAL
WHERE TO_CHAR(FromDate + LEVEL - 1, 'DY') NOT IN ('SAT', 'SUN')
CONNECT BY LEVEL <= ThruDate - FromDate + 1
) AS Weekday_Count
FROM myTable
The count is inclusive, meaning it includes FromDate and ThruDate. This query assumes that your dates don't have a time component; if they do you'll need to TRUNC the date columns in the subquery.
You could do it the following way :
Lets say we want to know how many weekdays between start_date='01.08.2013' and end_date='04.08.2013' In this example start_date and end_date are string literals. If your start_date and end_date are of date datatype, the TO_DATE() function won't be needed:
select count(*) as num_of_weekdays
from ( select level as dnum
from dual
connect by (to_date(end_date, 'dd.mm.yyyy') -
to_date(start_date, 'dd.mm.yyyy') + 1) - level >= 0) s
where to_char(sysdate + dnum, 'DY',
'NLS_DATE_LANGUAGE=AMERICAN') not in ('SUN', 'SAT')
Result:
num_of_weekdays
--------------
2
Checkout my complete working function code and explanation at
https://sqljana.wordpress.com/2017/03/16/oracle-calculating-business-days-between-two-dates-in-oracle/
Once you have created the function just use the function as part of the SELECT statement and pass in the two date columns for Start and End dates like this:
SELECT Begin_Date, End_Date, fn_GetBusinessDaysInterval(Begin_Date, End_Date) AS BusinessDays FROM YOURTABLE;

oracle SQL how to remove time from date

I have a column named StartDate containing a date in this format: 03-03-2012 15:22
What I need is to convert it to date. It should be looking like this: DD/MM/YYYY
What I have tried without success is:
select
p1.PA_VALUE as StartDate,
p2.PA_VALUE as EndDate
from WP_Work p
LEFT JOIN PARAMETER p1 on p1.WP_ID=p.WP_ID AND p1.NAME = 'StartDate'
LEFT JOIN PARAMETER p2 on p2.WP_ID=p.WP_ID AND p2.NAME = 'Date_To'
WHERE p.TYPE = 'EventManagement2'
AND TO_DATE(p1.PA_VALUE, 'DD/MM/YYYY') >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
AND TO_DATE(p2.PA_VALUE, 'DD/MM/YYYY') <= TO_DATE('26/10/2012', 'DD/MM/YYYY')
Is there a way to do this?
EDIT1: the PA_VALUE column is: VARCHAR2
You can use TRUNC on DateTime to remove Time part of the DateTime. So your where clause can be:
AND TRUNC(p1.PA_VALUE) >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
The TRUNCATE (datetime) function returns date with the time portion of
the day truncated to the unit specified by the format model.
When you convert your string to a date you need to match the date mask to the format in the string. This includes a time element, which you need to remove with truncation:
select
p1.PA_VALUE as StartDate,
p2.PA_VALUE as EndDate
from WP_Work p
LEFT JOIN PARAMETER p1 on p1.WP_ID=p.WP_ID AND p1.NAME = 'StartDate'
LEFT JOIN PARAMETER p2 on p2.WP_ID=p.WP_ID AND p2.NAME = 'Date_To'
WHERE p.TYPE = 'EventManagement2'
AND trunc(TO_DATE(p1.PA_VALUE, 'DD-MM-YYYY HH24:MI')) >= TO_DATE('25/10/2012', 'DD/MM/YYYY')
AND trunc(TO_DATE(p2.PA_VALUE, 'DD-MM-YYYY HH24:MI')) <= TO_DATE('26/10/2012', 'DD/MM/YYYY')
Outside the scope of the question, but storing dates as strings is bad practice, and storing date times is even worse.
We need to convert the strings to dates in order to do any form of date processing (arithmetic, interval assessment, etc) on them
Strings offer no guarantees regarding format, so we run the risk of date corruption crashing our code. We can defend against this by employing VALIDATE_CONVERSION() (available since 12c, find out more ) but it's still a PITN
Using non-standard datatypes makes it harder to reason about the data model and the code we build over it.
We can use TRUNC function in Oracle DB. Here is an example.
SELECT TRUNC(TO_DATE('01 Jan 2018 08:00:00','DD-MON-YYYY HH24:MI:SS')) FROM DUAL
Output:
1/1/2018
Try
SELECT to_char(p1.PA_VALUE,'DD/MM/YYYY') as StartDate,
to_char(p2.PA_VALUE,'DD/MM/YYYY') as EndDate
...
If your column with DATE datatype has value like below : -
value in column : 10-NOV-2005 06:31:00
Then, You can Use TRUNC function in select query to convert your date-time value to only date like - DD/MM/YYYY or DD-MON-YYYY
select TRUNC(column_1) from table1;
result : 10-NOV-2005
You will see above result - Provided that NLS_DATE_FORMAT is set as like below :-
Alter session NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
there is also extended usage like this:
WITH dates AS (
SELECT date'2015-01-01' d FROM dual union
SELECT date'2015-01-10' d FROM dual union
SELECT date'2015-02-01' d FROM dual union
SELECT timestamp'2015-03-03 23:45:00' d FROM dual union
SELECT timestamp'2015-04-11 12:34:56' d FROM dual
)
SELECT d "Original Date",
trunc(d) "Nearest Day, Time Removed",
trunc(d, 'ww') "Nearest Week",
trunc(d, 'iw') "Start of Week",
trunc(d, 'mm') "Start of Month",
trunc(d, 'year') "Start of Year"
FROM dates;
Oracle Offical Help Page

Oracle date function for the previous month

I have the query below where the date is hard-coded. My objective is to remove the harcoded date; the query should pull the data for the previous month when it runs.
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and TRUNC(CREATION_DATE) BETWEEN '01-AUG-2012' AND '31-AUG-2012'
Should I use sysdate-15 function for that?
Modifying Ben's query little bit,
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and creation_date between add_months(trunc(sysdate,'mm'),-1) and last_day(add_months(trunc(sysdate,'mm'),-1))
The trunc() function truncates a date to the specified time period; so trunc(sysdate,'mm') would return the beginning of the current month. You can then use the add_months() function to get the beginning of the previous month, something like this:
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and creation_date >= add_months(trunc(sysdate,'mm'),-1)
and creation_date < trunc(sysdate, 'mm')
As a little side not you're not explicitly converting to a date in your original query. Always do this, either using a date literal, e.g. DATE 2012-08-31, or the to_date() function, for example to_date('2012-08-31','YYYY-MM-DD'). If you don't then you are bound to get this wrong at some point.
You would not use sysdate - 15 as this would provide the date 15 days before the current date, which does not seem to be what you are after. It would also include a time component as you are not using trunc().
Just as a little demonstration of what trunc(<date>,'mm') does:
select sysdate
, case when trunc(sysdate,'mm') > to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as gt
, case when trunc(sysdate,'mm') < to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as lt
, case when trunc(sysdate,'mm') = to_date('20120901 00:00:00','yyyymmdd hh24:mi:ss')
then 1 end as eq
from dual
;
SYSDATE GT LT EQ
----------------- ---------- ---------- ----------
20120911 19:58:51 1
Data for last month-
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where dealer_name = 'XXXX'
and to_char(CREATION_DATE,'MMYYYY') = to_char(add_months(trunc(sysdate),-1),'MMYYYY');
I believe this would also work:
select count(distinct switch_id)
from xx_new.xx_cti_call_details#appsread.prd.com
where
dealer_name = 'XXXX'
and (creation_date BETWEEN add_months(trunc(sysdate,'mm'),-1) and trunc(sysdate, 'mm'))
It has the advantage of using BETWEEN which is the way the OP used his date selection criteria.
It is working with me in Oracle sql developer
SELECT add_months(trunc(sysdate,'mm'), -1),
last_day(add_months(trunc(sysdate,'mm'), -1))
FROM dual
Getting last nth months data retrieve
SELECT * FROM TABLE_NAME
WHERE DATE_COLUMN BETWEEN '&STARTDATE' AND '&ENDDATE';