I was trying to generate a monthly report but I have no idea how to break it down in weeks. e.g when i generate January my output report should be divided in 4 week - First week/Second week/Third week/Fourth week OF JANUARY - is this even possible? Should it be done before saving to database or SQL will do? I have a datetime field called RecordDate
I am using SQL Server 2005,VS 2010 and CR for VS2010.
Given your datetime field RecordDate, the following SQL will give the week of the month (starting at 1)
select (((datepart(d, RecordDate)-1) / 7)+1)
if you group by that, you should be able to produce a breakdown by the weeks in a month.
Of course, doing it this way some of the 'weeks' will not be 7 days long. It may be that you really want to group by the week of the year, ie.
select datepart(wk, RecordDate)
In each case you will need to produce labels. If you're going to do this in SQL then in the first case to get a label like 'week 1 of month 7' it'll be something like
select 'week ' + cast( (((datepart(d, RecordDate)-1) / 7)+1) as char(1))
+ ' of month ' + cast(datepart(month, RecordDate) as varchar(2))
from Table
group by (((datepart(d, RecordDate)-1) / 7)+1), datepart(month, RecordDate)
You'd have to go round the houses a bit to get a label like 'week 1 starting in month 7' for the second case (I will leave this as an exercise for the reader)
Related
Am getting the below issue when am using 'mon-d-yyyy' to convert date to char, as i need a single day digit for values from 1 to 9 days in a month.
When i use the 'mon-d-yyyy' format, am losing out on 5 days and getting a wrong date. Any help on this would be great.
select to_char(sysdate-22,'mon-d-yyyy') from dual;--aug-2-2017
select to_char(sysdate-22,'mon-dd-yyyy') from dual;--aug-07-2017
select sysdate-22 from dual;--07-AUG-17 11.06.43
In Oracle date formats, d gets the day of week. The 2 in your output means monday, not august the 2nd.
Try using Fill Mode as Format Model Modifier
select to_char(sysdate-22,'mon-fmdd-yyyy') from dual;
One option might be to piece together the date output you want:
SELECT
TO_CHAR(sysdate-22, 'mon-') ||
TRIM(LEADING '0' FROM TO_CHAR(sysdate-22, 'dd-')) ||
TO_CHAR(sysdate-22, 'yyyy')
FROM dual;
The middle term involving TRIM strips off the leading zeroes, if present, from the date.
Output:
Demo here:
Rextester
SQL>SELECT TO_CHAR(TO_DATE('29-AUG-2017','DD-MON-YYYY') - 22,'"WEEKDAY :"D, MON-FMDD-YYYY') "Before22Days" FROM DUAL;
D- Gives you a numeric weekday(2nd weekday in a week) on AUG-07-2017.
DD-Gives a Numeric Month Day i.e,07th
FMDD-Gives 7th
Before22Days
----------------------
WEEKDAY :2, AUG-7-2017
i'm trying to show some averages over the past 12 months but there is no data for June/July so i want the titles for the months to display but just 0's in the 3 columns
currently it's only showing August - May which is 10 rows so it's throwing off formulas and charts etc.
select to_char(Months.Period,'YYYY/MM') As Period, coalesce(avg(ec.hours_reset),0) as AvgOfHOURSReset, coalesce(AVG(ec.cycles_reset),0) as AvgofCycles_Reset, Coalesce(AVG(ec.days_reset),0) as AvgofDAYS_Reset
from (select distinct reset_date as Period from engineering_compliance
where reset_date between '01/JUN/15' and '31/MAY/16') Months
left outer join engineering_compliance ec on ec.reset_date = months.Period
WHERE EC.EO = 'AT CHECK'
group by to_char(Months.Period,'YYYY/MM')
order by to_char(Months.Period,'YYYY/MM')
;
(select distinct to_char(reset_date,'YYYY/MM') as Period from engineering_compliance
where reset_date between '01/JUN/15' and '31/MAY/16') Months;
That query is pretty good, it's not far from working.
You would need to replace the Months table part. You want exactly one row per month, regardless of whether there's any data in the ec table.
You could maybe synthesize some data without going to any actual table in your own schema.
For example:
SELECT
extract(month from add_months(sysdate,level-1)) Row_Month,
extract(year from add_months(sysdate,level-1)) Row_Year,
to_char(add_months(sysdate,level-1),'YYYY/MM') Formatted_Date,
trunc(add_months(sysdate,level-1),'mon') Join_Date
FROM dual
CONNECT BY level <= 12;
gives:
ROW_MONTH,ROW_YEAR,FORMATTED_DATE,JOIN_DATE
6,2016,'2016/06',1/06/2016
7,2016,'2016/07',1/07/2016
8,2016,'2016/08',1/08/2016
9,2016,'2016/09',1/09/2016
10,2016,'2016/10',1/10/2016
11,2016,'2016/11',1/11/2016
12,2016,'2016/12',1/12/2016
1,2017,'2017/01',1/01/2017
2,2017,'2017/02',1/02/2017
3,2017,'2017/03',1/03/2017
4,2017,'2017/04',1/04/2017
5,2017,'2017/05',1/05/2017
Option 1: Write that subselect inline into your query, replacing sysdate with the start month and the figure 12 on the last line can be altered for the number of months you want in the series.
Option 2 (can be reused more conveniently in a variety of situations and queries): Write a view with a long series of months (for example, Jan 1970 to Dec 2199) using my SQL above. You can then join to that view on join_date with whatever start and end months you want. It will give you one row per month and you can pick up the formatted date from its column.
I have a scenario where I need to compare 2 or more dates for given period.
I'm able to succeed when comparing 1 date to a period using between function. But challenge is when I have 2 dates to compare in parallel, getting single row sub query error
select A
from ORDER
where Date1 between sysdate and (sysdate-10)
Above query works fine for single date, please help to get a solution when I have Date 1 and Date 2 and need to compare against the same period (sysdate and (sysdate-10)) and I may have more than 2 dates as well.
Thanks
Shankar
Not having a proper description of your tables or the data they contain, it is difficult to know what you want.
Perhaps something like:
SELECT A
FROM ORDER
GROUP BY A
HAVING COUNT( CASE WHEN datecolumn BETWEEN SYSDATE - 10 AND SYSDATE THEN 1 ELSE NULL END ) > 0
I am working in oracle and new to coding and new to this site so I apologize in advance for the newbie question:
I have a script I am trying to run that will return the sum of next months' sales orders and compare that figure against our budgeted sales forecast. It was working great last month (November) when I set it up but now that it's December, I believe it's having problems figuring out that next month is a new year.
Essentially I just want to sum of our sales order records from the next month and compare that number against our forecast number.
Here is what I have so far (I'm sure I am making lots of grammatical mistakes so please be patient!)
select
"Backlog", "Forecast Amount" , round("Backlog"/"Forecast Amount",4) as "Backlog Percent"
from
(select round(sum(NVL(unit_price,0) *NVL( ship_quan,0)),2) as "Backlog"
from v_backlog_releases
where
(TO_CHAR(V_BACKLOG_RELEASES.PROMISE_DATE,'MM\YYYY') = TO_CHAR(sysdate,'MM\YYYY')+1)),
(select budamount as "Forecast Amount"
from
glbudget,
glperiods
where
glbudget.glperiods_id=glperiods.id and
TO_CHAR(GLPERIODS.START_DATE,'MM') = TO_CHAR(sysdate,'MM')+1)
The system won't let me post images of the output since I am too new. Essentially I should get something that looks like this:
Backlog | Forecast Amount | Backlog Percent
100,000 | 200,000 | .50
The backlog column is just a sum of ship quantities * price for all orders due to ship the following month.
Your issue is that for December TO_CHAR(sysdate, 'MM') + 1 is returning 13 instead of 1 of the next year. Obviously there is no month 13...
Try using ADD_MONTHS(sysdate, 1) instead and handle that result as appropriate. Best advice is to handle dates as dates instead of chars whenever possible.
Update based on comments:
Try using:
EXTRACT(MONTH FROM GLPERIODS.START_DATE) = EXTRACT(MONTH FROM ADD_MONTHS(sysdate, 1))
Documentation: https://docs.oracle.com/cd/B14117_01/server.101/b10759/functions045.htm
I have a table A which contains a Date type attribute. I want to write a query to select the date in another table B with value one month after the value in A.Any one know how to do it in oracle?
uhm... This was the first hit on google:
http://psoug.org/reference/date_func.html
It seems you're looking for the "add_months" function.
You need to use the ADD_MONTHS function in Oracle.
http://www.techonthenet.com/oracle/functions/add_months.php
Additional info: If you want to use this function with today's date you can use ADD_MONTHS(SYSDATE, 1) to get one month from now.
The question is to select a date_field from table b where date_field of table b is one month ahead of a date_field in table a.
An additional requirement must be taken into consideration which is currently unspecified in the question. Are we interested in whole months (days of month not taken into consideration) or do we want to include the days which might disqualify dates that are one month ahead but only by a couple of days (example: a=2011-04-30 and b=2011-05-01, b is 1 month ahead but only by 1 day).
In the first case, we must truncate both dates to their year and month values:
SELECT TRUNC( TO_DATE('2011-04-22','yyyy-mm-dd'), 'mm') as trunc_date
FROM dual;
gives:
trunc_date
----------
2011-04-01
In the second case we don't have to modify the dates.
At least two approaches can be used to solve the initial problem:
First one revolves around adding one month to the date_field in table a and finding a row in table b with a matching date.
SELECT b.date_field
FROM tab_a as a
,tab_b as b
WHERE ADD_MONTHS( TRUNC( a.date_field, 'mm' ), 1) = TRUNC( b.date_field, 'mm' )
;
Note the truncated dates. Leaving this out will require a perfect day to day match between dates.
The second approaches is based on calculating the difference in months between two dates and picking a calculation that gives a 1 month difference.
SELECT b.date_field
FROM tab_a as a
,tab_b as b
WHERE months_between( TRUNC( b.date_field, 'mm') , TRUNC(a.date_field, 'mm') ) = 1
The order of the fields in months_between is important here. In the provided example:
for b.date_field one month ahead of a.date_field the value is 1
for b.date_field one month before a.date_field the value is -1 (negative one)
Reversing the order will also reverse the results.
Hope this answers your question.