Oracle SQL Anniversary Dates Query - sql

I need some assistance in creating a query which shows the anniversary of employees in the business. I need the report to run and show results within two dates I select. I would like the report to show historical anniversary data too.
I would like columns NAME, ANNIVERSARY DATE, YEARS WITH BUSINESS
Columns I have in the dataset is name and date of employment.
Any help is appreciated!
TIA

Use MONTHS_BETWEEN and ADD_MONTHS:
SELECT name,
date_of_employment,
ADD_MONTHS(
date_of_employment,
(EXTRACT(YEAR FROM SYSDATE) - EXTRACT(YEAR FROM date_of_employment))*12
) AS anniversary,
MONTHS_BETWEEN(SYSDATE, date_of_employment)/12
AS years_with_business,
TRUNC(MONTHS_BETWEEN(SYSDATE, date_of_employment)/12)
AS full_years_with_business
FROM table_name;
Which, for the sample data:
CREATE TABLE table_name ( name, date_of_employment ) AS
SELECT 'Alice', ADD_MONTHS(TRUNC(SYSDATE - 1), -120) FROM DUAL UNION ALL
SELECT 'Beryl', ADD_MONTHS(TRUNC(SYSDATE + 0), -120) FROM DUAL UNION ALL
SELECT 'Carol', ADD_MONTHS(TRUNC(SYSDATE + 1), -120) FROM DUAL UNION ALL
SELECT 'Debra', ADD_MONTHS(TRUNC(SYSDATE - 1), +12) FROM DUAL UNION ALL
SELECT 'Emma', ADD_MONTHS(TRUNC(SYSDATE + 0), +12) FROM DUAL UNION ALL
SELECT 'Frances', ADD_MONTHS(TRUNC(SYSDATE + 1), +12) FROM DUAL;
Outputs:
NAME
DATE_OF_EMPLOYMENT
ANNIVERSARY
YEARS_WITH_BUSINESS
FULL_YEARS_WITH_BUSINESS
Alice
2011-08-18 00:00:00
2021-08-18 00:00:00
10.00435082511947431302270011947431302267
10
Beryl
2011-08-19 00:00:00
2021-08-19 00:00:00
10
10
Carol
2011-08-20 00:00:00
2021-08-20 00:00:00
9.99897448103345280764635603345280764633
9
Debra
2022-08-18 00:00:00
2021-08-18 00:00:00
-.9956491748805256869772998805256869773
0
Emma
2022-08-19 00:00:00
2021-08-19 00:00:00
-1
-1
Frances
2022-08-20 00:00:00
2021-08-20 00:00:00
-1.00102551896654719235364396654719235364
-1
db<>fiddle here

Related

How can a write a query for displaying which day of the week has see the least appointment requests?

A sample of data from my APPOINTMENT table
APP_ID A_DATE_TI PET_ID VN_ID
---------- --------- ---------- ----------
1 20-JAN-23 10001 801
2 20-JAN-23 10002 803
3 20-JAN-23 10003 804
4 20-JAN-23 10004 803
5 15-JAN-23 10005 801
6 14-JAN-23 10006 803
7 13-JAN-23 10007 804
8 12-JAN-23 10008 803
9 01-FEB-23 10009 801
10 02-FEB-23 10010 803
11 03-FEB-23 10011 804
SELECT
APP_ID,
TO_CHAR(A_DATE_TIME, 'DAY MONTH YYYY DD hh:mi') App_Date_Time,
PET_ID,
VN_ID
FROM APPOINTMENT
You can generate a list of all the days of the week and then LEFT OUTER JOIN to your appointments table and then ORDER the rows by the number of appointments and, from Oracle 12, FETCH FIRST ROW WITH TIES to find the minimum(s):
WITH days_of_week (day) AS (
SELECT TO_CHAR(TRUNC(SYSDATE, 'IW') + LEVEL - 1, 'DY')
FROM DUAL
CONNECT BY LEVEL <= 7
)
SELECT d.day,
COUNT(a.app_id) AS num_appointments
FROM days_of_week d
LEFT OUTER JOIN appointment a
ON d.day = TO_CHAR(a.A_DATE_TI, 'DY')
GROUP BY d.day
ORDER BY
num_appointments ASC
FETCH FIRST ROW WITH TIES;
Which, for the sample data:
CREATE TABLE appointment (APP_ID, A_DATE_TI, PET_ID, VN_ID) AS
SELECT 1, DATE '2023-01-20', 10001, 801 FROM DUAL UNION ALL
SELECT 2, DATE '2023-01-20', 10002, 803 FROM DUAL UNION ALL
SELECT 3, DATE '2023-01-20', 10003, 804 FROM DUAL UNION ALL
SELECT 4, DATE '2023-01-20', 10004, 803 FROM DUAL UNION ALL
SELECT 5, DATE '2023-01-15', 10005, 801 FROM DUAL UNION ALL
SELECT 6, DATE '2023-01-14', 10006, 803 FROM DUAL UNION ALL
SELECT 7, DATE '2023-01-13', 10007, 804 FROM DUAL UNION ALL
SELECT 8, DATE '2023-01-12', 10008, 803 FROM DUAL UNION ALL
SELECT 9, DATE '2023-02-01', 10009, 801 FROM DUAL UNION ALL
SELECT 10, DATE '2023-02-02', 10010, 803 FROM DUAL UNION ALL
SELECT 11, DATE '2023-02-03', 10011, 804 FROM DUAL;
Outputs:
DAY
NUM_APPOINTMENTS
TUE
0
MON
0
fiddle
SELECT TO_CHAR(a_date_time,'FMDay') day_of_week
,COUNT(*) number_of_appointments
FROM appointment
GROUP BY TO_CHAR(a_date_time,'FMDay')
ORDER BY number_of_appointments ASC
FETCH FIRST ROW WITH TIES
DAY_OF_WEEK
NUMBER_OF_APPOINTMENTS
Sunday
1
Wednesday
1
Saturday
1
You can determine the day of the week from your date column with
TO_CHAR(date A_DATE_TI, 'DAY')
So, you can use this query to find how many appointments occur on each weekday.
SELECT COUNT(*) appointments,
TO_CHAR(A_DATE_TI, 'DAY') weekday
FROM appointment
GROUP BY TO_CHAR(A_DATE_TI, 'DAY')
And this finds the day with the most appointments.
SELECT COUNT(*) appointments,
TO_CHAR(A_DATE_TI, 'DAY') weekday
FROM appointment
GROUP BY TO_CHAR(A_DATE_TI, 'DAY')
ORDER BY COUNT(*) DESC
LIMIT 1

SQL query to check if there are records in the database of 6 consecutive 'Sundays'

I need to build a query to check if there are records in the database of 6 consecutive 'Sundays'
SELECT DISTINCT ST1.DATAPU, ST1.NUMCAD, TO_CHAR(ST1.DATAPU, 'DAY') AS DIA
FROM SENIOR.R066SIT ST1
WHERE ST1.DATAPU BETWEEN '01/01/22' AND '23/11/22'
AND ST1.NUMCAD = 10
AND TO_CHAR(ST1.DATAPU, 'FMDAY') = 'DOMINGO' -->which is SUNDAY in English
ORDER BY ST1.DATAPU ASC
With this query above, I get the result of the records as shown in the image below
From Oracle 12, you can use MATCH_RECOGNIZE to perform row-by-row pattern analysis:
SELECT *
FROM (
SELECT DISTINCT
TRUNC(DATAPU) AS datapu,
NUMCAD,
TO_CHAR(DATAPU,'DAY') AS DIA
FROM SENIOR.R066SIT
WHERE DATAPU BETWEEN DATE '2022-01-01' AND DATE '2022-11-23'
AND NUMCAD = 10
AND TRUNC(DATAPU) - TRUNC(DATAPU, 'IW') = 6 -- Sunday
)
MATCH_RECOGNIZE(
ORDER BY datapu
ALL ROWS PER MATCH
PATTERN (first_week consecutive_week{5,})
DEFINE
consecutive_week AS PREV(datapu) + INTERVAL '7' DAY = datapu
)
Which, for the sample data:
CREATE TABLE senior.r066sit(numcad, datapu) AS
SELECT 10, DATE '2022-01-01' + LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 5*7
UNION ALL
SELECT 10, DATE '2022-04-01' + LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 7*7
UNION ALL
SELECT 10, DATE '2022-08-01' + LEVEL - 1 FROM DUAL CONNECT BY LEVEL <= 7*7;
Outputs:
DATAPU
NUMCAD
DIA
2022-04-03 00:00:00
10
SUNDAY
2022-04-10 00:00:00
10
SUNDAY
2022-04-17 00:00:00
10
SUNDAY
2022-04-24 00:00:00
10
SUNDAY
2022-05-01 00:00:00
10
SUNDAY
2022-05-08 00:00:00
10
SUNDAY
2022-05-15 00:00:00
10
SUNDAY
2022-08-07 00:00:00
10
SUNDAY
2022-08-14 00:00:00
10
SUNDAY
2022-08-21 00:00:00
10
SUNDAY
2022-08-28 00:00:00
10
SUNDAY
2022-09-04 00:00:00
10
SUNDAY
2022-09-11 00:00:00
10
SUNDAY
2022-09-18 00:00:00
10
SUNDAY
Before Oracle 12, you can use multiple analytic functions in nested sub-queries:
SELECT datapu, numcad,
TO_CHAR(datapu, 'fmDAY') AS dia
FROM (
SELECT datapu, numcad,
COUNT(*) OVER (PARTITION BY grp) AS grp_size
FROM (
SELECT datapu, numcad,
SUM(consecutive) OVER (ORDER BY datapu) AS grp
FROM (
SELECT datapu, numcad,
CASE datapu - LAG(datapu) OVER (ORDER BY datapu)
WHEN 7
THEN 0
ELSE 1
END AS consecutive
FROM (
SELECT DISTINCT
TRUNC(DATAPU) AS datapu,
NUMCAD
FROM SENIOR.R066SIT
WHERE DATAPU BETWEEN DATE '2022-01-01' AND DATE '2022-11-23'
AND NUMCAD = 10
AND TRUNC(DATAPU) - TRUNC(DATAPU, 'IW') = 6 -- Sunday
)
)
)
)
WHERE grp_size >= 6;
fiddle

Hierarchical query using oracle SQL

We have following table to query data from,
EMPLOYEE_ABSENCE_TAB
emp_id
absence_id
from_date
to_date
absence_continuation
100
1
01/01/2022
03/01/2022
100
2
01/02/2022
05/02/2022
1
200
3
01/01/2022
07/01/2022
200
4
10/01/2022
14/01/2022
3
200
5
16/01/2022
20/01/2022
4
300
6
01/01/2022
14/01/2022
We need to connect data hierarchically based on the following logic.
Output should be emp_id, absence_days, from_date and to_date.
absence_days : number of absence days = sum(to_date - from_date)
from_date : first from_date where absence_continuation is NULL
to_date : last to_date connect by prior absence_id = absence_continuation
Expected Outcome
emp_id
absence_days
from_date
to_date
100
8
01/01/2022
05/02/2022
200
17
01/01/2022
20/01/2022
300
14
01/01/2022
14/01/2022
I tried hierarchical but could able to come up with working solution. How can this be achieved using hierarchical query in Oracle SQL?
You don't need to consider the hierarchy in the data (assuming that there are no overlaps); you just need to aggregate:
SELECT emp_id,
SUM(to_date - from_date + 1) AS absence_days,
MIN(from_date) AS from_date,
MAX(to_date) AS to_date
FROM EMPLOYEE_ABSENCE_TAB
GROUP BY emp_id
Which, for the sample data:
CREATE TABLE EMPLOYEE_ABSENCE_TAB
(emp_id, absence_id, from_date, to_date, absence_continuation) AS
SELECT 100, 1, DATE '2022-01-01', DATE '2022-01-03', NULL FROM DUAL UNION ALL
SELECT 100, 2, DATE '2022-02-01', DATE '2022-02-05', 1 FROM DUAL UNION ALL
SELECT 200, 3, DATE '2022-01-01', DATE '2022-01-07', NULL FROM DUAL UNION ALL
SELECT 200, 4, DATE '2022-01-10', DATE '2022-01-14', 3 FROM DUAL UNION ALL
SELECT 200, 5, DATE '2022-01-16', DATE '2022-01-20', 4 FROM DUAL UNION ALL
SELECT 300, 6, DATE '2022-01-01', DATE '2022-01-14', NULL FROM DUAL;
Outputs:
EMP_ID
ABSENCE_DAYS
FROM_DATE
TO_DATE
100
8
2022-01-01 00:00:00
2022-02-05 00:00:00
200
17
2022-01-01 00:00:00
2022-01-20 00:00:00
300
14
2022-01-01 00:00:00
2022-01-14 00:00:00
If you did want to consider the hierarchy and get the duration of each absence (and not the total absences per employee) then you can use:
SELECT emp_id,
absence_id,
SUM(to_date - from_date + 1) AS absence_days,
MIN(from_date) AS from_date,
MAX(to_date) AS to_date
FROM (
SELECT emp_id,
CONNECT_BY_ROOT absence_id AS absence_id,
to_date - from_date + 1 AS absence_days,
from_date,
to_date
FROM EMPLOYEE_ABSENCE_TAB
START WITH absence_continuation IS NULL
CONNECT BY PRIOR absence_id = absence_continuation
)
GROUP BY
emp_id,
absence_id
Which outputs the same (with an additional absence_id column for the id of the first part of the absence) for your sample data as you only have a single absence for each employee; if you had more absences then it would aggregate each absence separately.
db<>fiddle here

CONSECUTIVE DAYS QUERY [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
I have an Oracle DB Connection that has data (SELECT * FROM SALES) as in the picture, i want a query that gives me which 3 consecutive days are those who have the sum of PREMIUM_TOTAL > 100.
I have tried with the method lead, lag , DATADIFF but failed. Also i'm new at this, if you can give me hints please.
If you want 3 rows from successive days then you can use a recursive query:
WITH successive_days (day, products, total, depth) AS (
SELECT entry_date,
TO_CHAR(product_id),
premium_total,
1
FROM table_name
UNION ALL
SELECT s.day + 1,
s.products || ',' || t.product_id,
s.total + t.premium_total,
s.depth + 1
FROM successive_days s
INNER JOIN table_name t
ON (s.day + 1 = t.entry_date)
WHERE s.depth < 3
)
SELECT day AS final_day, products, total
FROM successive_days
WHERE depth = 3
AND total >= 100;
Which, for the sample data:
CREATE TABLE table_name (product_id, entry_date, premium_total) AS
SELECT 1, DATE '2022-03-01', 1 FROM DUAL UNION ALL
SELECT 2, DATE '2022-03-01', 20 FROM DUAL UNION ALL
SELECT 4, DATE '2022-03-02', 30 FROM DUAL UNION ALL
SELECT 5, DATE '2022-03-03', 30 FROM DUAL UNION ALL
SELECT 10, DATE '2022-03-21', 12 FROM DUAL UNION ALL
SELECT 11, DATE '2022-03-31', 40.5 FROM DUAL UNION ALL
SELECT 13, DATE '2022-03-05', 70 FROM DUAL UNION ALL
SELECT 12, DATE '2022-03-05', 80 FROM DUAL UNION ALL
SELECT 14, DATE '2022-03-05', 10 FROM DUAL UNION ALL
SELECT 20, DATE '2022-03-06', 20 FROM DUAL UNION ALL
SELECT 21, DATE '2022-03-07', 30 FROM DUAL UNION ALL
SELECT 22, DATE '2022-03-07', 40 FROM DUAL UNION ALL
SELECT 30, DATE '2022-03-08', 20 FROM DUAL UNION ALL
SELECT 31, DATE '2022-03-09', 50 FROM DUAL UNION ALL
SELECT 40, DATE '2022-03-10', 2 FROM DUAL;
Outputs:
FINAL_DAY
PRODUCTS
TOTAL
2022-03-07 00:00:00
13,20,21
120
2022-03-07 00:00:00
13,20,22
130
2022-03-07 00:00:00
12,20,21
130
2022-03-07 00:00:00
12,20,22
140
2022-03-09 00:00:00
21,30,31
100
2022-03-09 00:00:00
22,30,31
110
If you want all the rows (at least 3) that are all within 3 successive days then you can use MATCH_RECOGNIZE:
SELECT MIN(entry_date) AS start_day,
MAX(entry_date) AS final_day,
LISTAGG(product_id, ',') WITHIN GROUP (ORDER BY entry_date) AS products,
SUM(premium_total) AS total
FROM table_name
MATCH_RECOGNIZE(
ORDER BY entry_date
MEASURES
MATCH_NUMBER() AS mno
ALL ROWS PER MATCH
AFTER MATCH SKIP TO NEXT ROW
PATTERN (first_day+ second_day+ third_day* final_day)
DEFINE
first_day AS FIRST(entry_date) = entry_date,
second_day AS FIRST(entry_date) + 1 = entry_date,
third_day AS FIRST(entry_date) + 2 = entry_date,
final_day AS FIRST(entry_date) + 2 = entry_date
AND SUM(premium_total) >= 100
)
GROUP BY mno;
Which, for the sample data, outputs:
START_DAY
FINAL_DAY
PRODUCTS
TOTAL
2022-03-05 00:00:00
2022-03-07 00:00:00
12,13,14,20,21,22
250
2022-03-05 00:00:00
2022-03-07 00:00:00
13,14,20,21,22
170
2022-03-05 00:00:00
2022-03-07 00:00:00
13,20,21,22
160
2022-03-06 00:00:00
2022-03-08 00:00:00
20,21,22,30
110
2022-03-07 00:00:00
2022-03-09 00:00:00
21,22,30,31
140
2022-03-07 00:00:00
2022-03-09 00:00:00
22,30,31
110
db<>fiddle here

Querying the weeks for the whole month and displaying the content according to that month

I have a question regarding my analysis programming. I already have a query to show the weeks in a whole year. But im stuck when i need to sum up values regarding to each week's occurence. So this is my SQL code,
SELECT LEVEL WEEK_NUM_INCR,
TO_CHAR (start_date + (LEVEL - 1) * 7, 'WW') WEEK_POSITION /* WEEK POSITION FOR THE WHOLE YEAR */
,
TO_CHAR (start_date + (LEVEL - 1) * 7, 'DD-MM-YYYY') START_WEEK_DATE,
TO_CHAR (start_date + (LEVEL) * 7, 'DD-MM-YYYY') END_WEEK_DATE,
(SELECT SUM(ONSITE_UPD_QTY) FROM DTL_ERC_UPD#WELTES_SITEMON_LINK WHERE UPD_DATE BETWEEN
TO_CHAR (start_date + (LEVEL) * 7, 'MM/DD/YYYY') AND TO_CHAR (start_date + (LEVEL) * 7, 'MM/DD/YYYY') CONNECT BY start_date + (LEVEL - 1) * 7 < end_date)
FROM (SELECT TO_DATE ('01/01/2015', 'MM/DD/YYYY') start_date,
TO_DATE ('12/31/2015', 'MM/DD/YYYY') end_date
FROM DUAL)
CONNECT BY start_date + (LEVEL - 1) * 7 < end_date;
it would display the weeks but when i added this part in the middle which i have now,
(SELECT SUM(ONSITE_UPD_QTY) FROM DTL_ERC_UPD#WELTES_SITEMON_LINK WHERE UPD_DATE BETWEEN
TO_CHAR (start_date + (LEVEL) * 7, 'MM/DD/YYYY') AND TO_CHAR (start_date + (LEVEL) * 7, 'MM/DD/YYYY') CONNECT BY start_date + (LEVEL - 1) * 7 < end_date)
it throws these errors,
ORA-01843: not a valid month
ORA-02063: preceding line from WELTES_SITEMON_LINK
So for the DTL_ERC_UPD, I have
ONSITE_UPD_QTY UPD_DATE
1 2/5/2015 12:00:01 AM
1 2/5/2015 12:00:01 AM
1 2/4/2015
1 2/4/2015
1 2/4/2015
I am hoping that it would show 5 during feb 1st until 8th and zero on the rest of the row.
Please help me with this issue
below one is the sample table
select cast('01/08/2013' as Date) dte INTO #temp union all select
'03/01/2013' union all select
'11/01/2013' union all select
'12/01/2013' union all select
'10/21/2014' union all select
'10/27/2014' union all select
'10/30/2014' union all select
'10/31/2014' union all select
'11/01/2014' union all select
'11/02/2014' union all select
'11/04/2014' union all select
'11/05/2014' union all select
'11/08/2014' union all select
'11/09/2014' union all select
'11/11/2014' union all select
'11/20/2014' union all select
'11/07/2014' union all select
'07/11/2014' union all select
'11/13/2013' union all select
'09/01/2014' union all select
'11/03/2014' union all select
'11/18/2014' union all select
'12/05/2014' union all select
'07/24/2014' union all select
'07/26/2014' union all select
'07/27/2014' union all select
'07/28/2014' union all select
'07/29/2014' union all select
'07/30/2014' union all select
'01/01/2014' union all select
'02/01/2014' union all select
'04/01/2014' union all select
'05/01/2014' union all select
'06/01/2014' union all select
'06/01/2014' union all select
'07/01/2014' union all select
'07/01/2014' union all select
'11/05/2013' union all select
'06/16/2014' union all select
'06/17/2014' union all select
'06/18/2014' union all select
'06/19/2014' union all select
'06/20/2014' union all select
'06/21/2014' union all select
'06/22/2014' union all select
'06/23/2014' union all select
'06/24/2014' union all select
'06/25/2014' union all select
'06/26/2014' union all select
'06/27/2014' union all select
'06/28/2014' union all select
'06/29/2014'
now you can get week count start date of the week and end date of the week
select count([Week]) cont,[Week],
DATEADD(Day,(cast(SUBSTRING([Week],5,LEN( [Week])) as integer)*7)-7,
DATEADD(year,cast(SUBSTRING([Week],1,4) as integer)-1900,0)) startDte,
DATEADD(Day,cast(SUBSTRING([Week],5,LEN( [Week])) as integer)*7,
DATEADD(year,cast(SUBSTRING([Week],1,4) as integer)-1900,0)) endDte
from (select cast(datepart(YYYY,cast(dte as DATE)) as varchar(4))+''+cast(datepart(WW,cast(dte as DATE)) as varchar(2)) [Week],dte from #temp
) AS temp GROUP BY [Week]
ouput is
cont startDte endDte
1 2013-01-08 00:00:00.000 2013-01-15 00:00:00.000
1 2013-10-29 00:00:00.000 2013-11-05 00:00:00.000
1 2013-11-05 00:00:00.000 2013-11-12 00:00:00.000
1 2013-11-12 00:00:00.000 2013-11-19 00:00:00.000
1 2013-12-03 00:00:00.000 2013-12-10 00:00:00.000
1 2013-02-26 00:00:00.000 2013-03-05 00:00:00.000
1 2014-01-01 00:00:00.000 2014-01-08 00:00:00.000
1 2014-04-02 00:00:00.000 2014-04-09 00:00:00.000
1 2014-04-30 00:00:00.000 2014-05-07 00:00:00.000
2 2014-06-04 00:00:00.000 2014-06-11 00:00:00.000
6 2014-06-18 00:00:00.000 2014-06-25 00:00:00.000
7 2014-06-25 00:00:00.000 2014-07-02 00:00:00.000
3 2014-07-02 00:00:00.000 2014-07-09 00:00:00.000
1 2014-07-09 00:00:00.000 2014-07-16 00:00:00.000
2 2014-07-23 00:00:00.000 2014-07-30 00:00:00.000
4 2014-07-30 00:00:00.000 2014-08-06 00:00:00.000
1 2014-09-03 00:00:00.000 2014-09-10 00:00:00.000
1 2014-10-22 00:00:00.000 2014-10-29 00:00:00.000
4 2014-10-29 00:00:00.000 2014-11-05 00:00:00.000
6 2014-11-05 00:00:00.000 2014-11-12 00:00:00.000
2 2014-11-12 00:00:00.000 2014-11-19 00:00:00.000
2 2014-11-19 00:00:00.000 2014-11-26 00:00:00.000
1 2014-12-03 00:00:00.000 2014-12-10 00:00:00.000
1 2014-01-29 00:00:00.000 2014-02-05 00:00:00.000
Second connect by in your code is needless. Organize query in logical sections using proper join. Do not use date to char conversion for comparison, as already mentioned. Below is sample query that you can use:
with period as (
select to_date('02/01/2015', 'MM/DD/YYYY') start_date,
to_date('03/01/2015', 'MM/DD/YYYY') end_date from dual),
weeks as (
select level week_num_inc,
to_char(start_date + (level - 1) * 7, 'WW') week_position,
start_date + (level - 1) * 7 start_week_date,
start_date + level * 7 end_week_date
from period
connect by start_date + (level - 1) * 7 < end_date)
select week_num_inc, week_position, start_week_date, end_week_date,
nvl(sum(dtl_erc_upd.onsite_upd_qty), 0) quantity
from weeks w
left join dtl_erc_upd on start_week_date <= upd_date
and upd_date < end_week_date
group by week_num_inc, week_position, start_week_date, end_week_date
order by start_week_date
result:
WEEK_NUM_INC WEEK_POSITION START_WEEK_DATE END_WEEK_DATE QUANTITY
1 05 2015-02-01 2015-02-08 5
2 06 2015-02-08 2015-02-15 0
3 07 2015-02-15 2015-02-22 0
4 08 2015-02-22 2015-03-01 0