This work fine:
SELECT INTERVAL '1:0:0' HOUR TO SECOND FROM dual;
I'm trying to select some value from table and use it as INTERVAL. How can I use subquery instead of '1:0:0'?
SELECT INTERVAL (SELECT some_varchar_value from some_table) HOUR TO SECOND FROM DUAL;
But INTERVAL expects expression within single quotes ' '
You can use the TO_DSINTERVAL() function:
SELECT TO_DSINTERVAL(some_varchar_value)
FROM some_table;
But your string value needs to be in the right format. If it as shown, with just hours, minutes and seconds, you need to prepend a dummy zero for the number of days:
with some_table(some_varchar_value) as (
select '1:0:0' from dual
)
SELECT TO_DSINTERVAL('0 ' || some_varchar_value)
FROM some_table;
TO_DSINTERV
-----------
0 1:0:0.0
If your hours value can be greater than 24 then you will need to split that into whole days and the remaining hours:
with some_table(some_varchar_value) as (
select '1:2:3' from dual
union all select '99:45:15' from dual
)
SELECT TO_DSINTERVAL(
floor(to_number(regexp_substr(some_varchar_value, '[^:]+', 1, 1)) / 24)
|| ' ' || mod(to_number(regexp_substr(some_varchar_value, '[^:]+', 1, 1)), 24)
|| ':' || regexp_substr(some_varchar_value, '[^:]+', 1, 2)
|| ':' || regexp_substr(some_varchar_value, '[^:]+', 1, 3)
)
FROM some_table;
TO_DSINTERV
-----------
0 1:2:3.0
4 3:45:15.0
The inner part of that is splitting the original string into separate hour, minute and second components; the hour is then separate into days with floor(hours / 24) and the remaining hours with mod(hours, 24). You can see that more clearly with:
with some_table(some_varchar_value) as (
select '99:59:30' from dual
)
SELECT regexp_substr(some_varchar_value, '[^:]+', 1, 1), regexp_substr(some_varchar_value, '[^:]+', 1, 2), regexp_substr(some_varchar_value, '[^:]+', 1, 3)
FROM some_table;
with some_table(some_varchar_value) as (
select '1:2:3' from dual
union all select '99:45:15' from dual
)
SELECT regexp_substr(some_varchar_value, '[^:]+', 1, 1) as raw_hh,
regexp_substr(some_varchar_value, '[^:]+', 1, 2) as raw_mi,
regexp_substr(some_varchar_value, '[^:]+', 1, 3) as raw_ss,
floor(to_number(regexp_substr(some_varchar_value, '[^:]+', 1, 1)) / 24) as new_dd,
mod(to_number(regexp_substr(some_varchar_value, '[^:]+', 1, 1)), 24) as new_hh
FROM some_table;
RAW_HH RAW_MI RAW_SS NEW_DD NEW_HH
-------- -------- -------- ---------- ----------
1 2 3 0 1
99 45 15 4 3
Related
I need to extract the date (08-01-2021) from the below string that has no whitespace
select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' from dual
I tried to apply the REGEXP_SUBSTR function as shown below, but using this query I just removed 'Date-'
with x as
(select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' as str
from dual)
SELECT REGEXP_SUBSTR(STR, 'Date-([^ ]+)',1,1,'i',1)
FROM x;
Please advise
You are zero-padding the date values so each term has a fixed length and have a fixed prefix so you do not need to use (slow) regular expressions and can just use simple string functions:
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY')
FROM table_name;
(Note: if you still want it as a string, rather than as a date, then just use SUBSTR without wrapping it in TO_DATE.)
For example:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Outputs:
DATE_VALUE
08-JAN-21
db<>fiddle here
If the Date- prefix is not going to always be at the start then use INSTR to find it:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'Trans-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, INSTR(value, 'Date-') + 5, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Which outputs:
DATE_VALUE
08-JAN-21
08-FEB-21
If you can have multiple Date- substrings and you want to find the one that is either at the start of the string or has a - prefix then you may need regular expressions:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'TransDate-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(
REGEXP_SUBSTR(value, '(^|-)Date-(\d\d-\d\d-\d{4})([-.]|$)', 1, 1, 'i', 2),
'DD-MM-YYYY'
) AS date_value
FROM table_name;
db<>fiddle here
Just use a more precise regular expression:
SELECT REGEXP_SUBSTR(STR, 'Date-([0-9]{2}-[0-9]{2}-[0-9]{4})', 1, 1, 'i', 1)
FROM x;
Or for less accuracy but more conciseness:
SELECT REGEXP_SUBSTR(STR, 'Date-([-0-9]{10})', 1, 1, 'i', 1)
Long story short, I was handed this query (edited a bit for the forum world) to get it working in order to start creating reports. Having some issues with the 3 CASE statements (tried to add comment within the code to explain a little better what is happening). All data is being pulled from the same table/view.
I know I need to create some nested SELECT statements in order to make it work, but I'm struggling. What I'm trying to have happen is...
CASE 2 to only run if CASE 1 IS NOT NULL, where the column would be a result of (amd_month + 1 month). Format being YYYYMM
CASE 3 to only run if CASE 2 IS NOT NULL, where the column would be a result of (ext_srg_start_date + 6 months). Format being YYYYMM
SELECT
part,
amd_month,
amd actual_demand,
round(roll_12amd * 1.15) srg_lmt,
round(roll_12amd * 1.5) ext_srg_lmt,
-- CASE: 1
-- calculate level- COMPLETE
CASE
WHEN (amd > roll_12amd * 1.5) THEN 'Extreme Surge'
WHEN (amd > roll_12amd * 1.15) THEN 'Surge'
ELSE NULL
END AS srg_nt,
-- CASE: 2
-- if amd_month = 12, (+1 year to) and (-11 from month) from ext_srg_start_date,
-- else +1 month to ext_srg_start_date - COMPLETE
CASE
WHEN substr(amd_month, 5, 2) IN (
'12'
) THEN concat(TO_CHAR(substr(amd_month, 1, 4) + 1), lpad(TO_CHAR(substr(amd_month, 5, 2) - 11), 2, '0'))
ELSE concat(substr(amd_month, 1, 4), lpad(TO_CHAR(substr(amd_month, 5, 2) + 1), 2, '0'))
END AS ext_srg_start_date,
---- CASE: 3
---- +6 to ext_srg_start_date - IN PROGRESS
CASE
WHEN substr(amd_month, 5, 2) IN (
'01',
'02',
'03',
'04',
'05',
'06'
) THEN concat(substr(amd_month, 1, 4), lpad(TO_CHAR(substr(amd_month, 5, 2) + 6), 2, '0'))
ELSE concat(TO_CHAR(substr(amd_month, 1, 4) + 1), lpad(TO_CHAR(substr(amd_month, 5, 2) - 6), 2, '0'))
END AS ext_srg_carry_date
FROM
connect.table
Any help would be awesome. Thanks!
You can do away with case statements 2 and 3 if AMD_Month is a date data type, you can also do away with them if it's not but it takes an extra step:
If AMD_Month is a Date column then ext_srg_start_date and ext_srg_carry_date could be defined as:
...
, AMD_Month + INTERVAL '1' MONTH ext_srg_start_date
, AMD_Month + INTERVAL '6' MONTH ext_srg_carry_date
...
If AMD_Month is a string, then you first need to convert it to a date and I guess then convert the result back to a string:
...
, TO_CHAR( TO_DATE( AMD_Month, 'YYYYMM')
+ INTERVAL '1' MONTH, 'YYYYMM') ext_srg_start_date
, TO_CHAR( TO_DATE( AMD_Month, 'YYYYMM')
+ INTERVAL '6' MONTH, 'YYYYMM') ext_srg_carry_date
...
Date arithmatic works so much better when you store date data types as dates or timestamps than when you store them as strings.
I have a column called duration_d which is varchar2 and the data in that table looks like below
duration_d
-----------
12:25
01:35
12:10
04:21
12:18
12:24
I tried below query
SELECT SUM( to_date( duration_d, 'mi:ss' ))
FROM table
GROUP BY calling_number;
When I execute it following error is coming
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
can any one tell me how to make sum it?
To get the total as fractions of a day you can use:
SELECT SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ) AS total
FROM your_table
Which gives the result:
TOTAL
------------------------------------------
0.0383449074074074074074074074074074074074
To convert this to an interval data type you can use NUMTODSINTERVAL:
SELECT NUMTODSINTERVAL(
SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ),
'DAY'
) AS total
FROM your_table
Which gives the result:
TOTAL
-------------------
+00 00:55:13.000000
Please try below:
with x as
(select sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE)
SELECT
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Will work only if the duration is always [MI:SS].
Also you can add the group by as per your requirement.
Converting Seconds to the required duration format Reference.
Group By
with x as
(select calling_number,sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE
group by calling_number)
SELECT calling_number,
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Use a combination of SUBSTR, to_char, to_date, NVL, INSTR, reverse and SUM.
SELECT "calling_number",
to_char(to_date(SUM(NVL(SUBSTR("duration_d", 0, INSTR("duration_d", ':')-1), "duration_d"))*60 +
SUM(substr("duration_d", - instr(reverse("duration_d"), ':') + 1)),'sssss'),'hh24:mi:ss') AS SUM_DURATION_D
FROM yourtable
GROUP BY "calling_number"
Output
calling_number SUM_DURATION_D
1 00:26:10
2 00:29:03
SQL Fiddle: http://sqlfiddle.com/#!4/9b0a81/33/0
Correct spelling as below
SELECT SUM( TO_DATE( duration_d, 'mi:ss' ) )
FROM YOURTABLE Group By calling_number
I need help writing a aging report on oracle.
The report should be like:
aging file to submit total 17
aging file to submit 0-2 days 3
aging file to submit 2-4 days 4
aging file to submit 4-6 days 4
aging file to submit 6-8 days 2
aging file to submit 8-10 days 4
I can create a query for each section and then union all the the results like:
select 'aging file to submit total ' || count(*) from FILES_TO_SUBMIT where trunc(DUE_DATE) > trunc(sysdate) -10
union all
select 'aging file to submit 0-2 days ' || count(*) from FILES_TO_SUBMIT where trunc(DUE_DATE) <= trunc(sysdate) and trunc(DUE_DATE) >= trunc(sysdate-2)
union all
select 'aging file to submit 2-4 days ' || count(*) from FILES_TO_SUBMIT where trunc(DUE_DATE) <= trunc(sysdate-2) and trunc(DUE_DATE) >= trunc(sysdate-4) ;
I was wondering if there is a better way using oracle analytic functions or any other query that will get better performance?
Sample data:
CREATE TABLE files_to_submit(file_id int, file_name varchar(255),due_date date);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 1, 'file_' || 1, sysdate);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 2, 'file_' || 2, sysdate -5);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 3, 'file_' || 3, sysdate -4);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 4, 'file_' || 4, sysdate);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 5, 'file_' || 5, sysdate-3);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 6, 'file_' || 6, sysdate-7);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 7, 'file_' || 7, sysdate-10);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 8, 'file_' || 8, sysdate-12);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 9, 'file_' || 9, sysdate-3);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 10, 'file_' || 10, sysdate-5);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 11, 'file_' || 11, sysdate-6);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 12, 'file_' || 12, sysdate-7);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 13, 'file_' || 13, sysdate-5);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 14, 'file_' || 14, sysdate-4);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 15, 'file_' || 15, sysdate-2);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 16, 'file_' || 16, sysdate-6);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 17, 'file_' || 17, sysdate-6);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 18, 'file_' || 18, sysdate-5);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 19, 'file_' || 19, sysdate-10);
INSERT INTO FILES_TO_SUBMIT(FILE_ID,FILE_NAME,DUE_DATE) VALUES ( 20, 'file_' || 20, sysdate-9);
DROP TABLE files_to_submit;
you can use this simple approach to get the report for all days(without total):
select
'aging file to submit '|| trunc(dist/2)*2 ||'-'|| (trunc(dist/2)*2+2) || ' days: ' || count(*)
from (
select trunc(sysdate) - trunc(DUE_DATE) as dist
from FILES_TO_SUBMIT
--where trunc(DUE_DATE) > trunc(sysdate) -10
)
group by trunc(dist/2)
order by trunc(dist/2);
The only thing that is important is just number of days (dist(ance) field).
If you want to have also the Total in the same scan:
select
'aging file to submit '||
case
when trunc(dist/2) is null
then 'Total '
else trunc(dist/2)*2 ||'-'|| (trunc(dist/2)*2+2) || ' days: '
end ||
count(*)
from (
select trunc(sysdate) - trunc(DUE_DATE) as dist
from FILES_TO_SUBMIT
where trunc(DUE_DATE) > trunc(sysdate) -10
)
group by rollup(trunc(dist/2))
order by trunc(dist/2)
nulls first;
Hint: If you have hundreds of days of history an index would be useful. (pay attention: if your table is very big, >100Milion, the creation of the index will take some time)
create index index_name on files_to_submit(due_date);
and then change the condition to:
where DUE_DATE > trunc(sysdate) - 10
This will speed up y
Allow me to suggest WIDTH_BUCKET.
This will divide the date range into equal size. Since you want 10 days range into groups of 2 days, the bucket size will be 10 / 2 = 5.
Query:
SELECT
CASE GROUPING(bucket)
WHEN 1
THEN 'aging file to submit Total'
ELSE 'aging file to submit ' || (bucket-1)*2 || '-' || (bucket)*2 || ' days'
END AS bucket_number,
COUNT(1) AS files
FROM (
SELECT
WIDTH_BUCKET(due_date, sysdate, sysdate-10, 5) bucket
FROM
files_to_submit
WHERE
due_date >= sysdate-10
)
GROUP BY
ROLLUP(bucket)
ORDER BY
bucket NULLS FIRST;
Result:
BUCKET_NUMBER FILES
------------------------------------ ----------
aging file to submit Total 17
aging file to submit 0-2 days 2
aging file to submit 2-4 days 3
aging file to submit 4-6 days 6
aging file to submit 6-8 days 5
aging file to submit 8-10 days 1
I got different counts using your sample data -- I get 19 total instead of 17 (which seems appropriate as only one of the 20 records in your sample data is out of the range):
WITH d1 AS (
SELECT 2 AS day_cnt FROM dual
UNION ALL
SELECT 4 FROM dual
UNION ALL
SELECT 6 FROM dual
UNION ALL
SELECT 8 FROM dual
UNION ALL
SELECT 10 FROM dual
)
SELECT NVL(title, 'aging file to submit total') AS title, COUNT(DISTINCT file_id)
FROM (
SELECT 'aging file to submit ' || prev_day || '-' || day_cnt || ' days' AS title, f1.file_id
FROM (
SELECT day_cnt, NVL(LAG(day_cnt) OVER ( ORDER BY day_cnt ), 0) AS prev_day
FROM d1
) d2, files_to_submit f1
WHERE TRUNC(f1.due_date) <= TRUNC(SYSDATE - d2.prev_day)
AND TRUNC(f1.due_date) >= TRUNC(SYSDATE - d2.day_cnt)
) GROUP BY ROLLUP(title);
Also, the counts for the day ranges aren't right (they don't add up to 19, that is) because of the the files can be counted twice due to the use of TRUNC() and including both end cases. But I'm sure you can tweak the above to give what you want.
WITH r (
'aging file to submit ' Prefix,
Total,
Days0_2,
Days2_4,
Days4_6,
Days6_8,
Days8_10
) AS (
SELECT
SUM(Total) Total,
SUM(Days0_2) Days0_2,
SUM(Days2_4) Days2_4,
SUM(Days4_6) Days4_6,
SUM(Days6_8) Days6_8,
SUM(Days8_10) Days8_10
FROM (
SELECT
(CASE WHEN f.days <= 2 THEN f.num ELSE NULL END) AS Days0_2,
(CASE WHEN f.days >= 2 AND f.days <= 4 THEN f.num ELSE NULL END) AS Days2_4,
(CASE WHEN f.days >= 4 AND f.days <= 6 THEN f.num ELSE NULL END) Days4_6,
(CASE WHEN f.days >= 6 AND f.days <= 8 THEN f.num ELSE NULL END) AS Days6_8,
(CASE WHEN f.days >= 8 AND f.days <= 10 THEN f.num ELSE NULL END) AS Days8_10,
f.num AS Total
FROM (
SELECT
COUNT(*) AS num,
TRUNC(due_date) - TRUNC(SYSDATE) + 10 AS days
FROM FILES_TO_SUBMIT t
WHERE (TRUNC(due_date) - TRUNC(SYSDATE) + 10) >= 0
GROUP BY TRUNC(due_date) - TRUNC(SYSDATE) + 10
) f
) s
)
SELECT Prefix || 'Total' AS Label, Total AS Count FROM r
UNION ALL SELECT Prefix || '0-2 days', Days0_2 FROM r
UNION ALL SELECT Prefix || '2-4 days', Days2_4 FROM r
UNION ALL SELECT Prefix || '4-6 days', Days4_6 FROM r
UNION ALL SELECT Prefix || '6-8 days', Days6_8 FROM r
UNION ALL SELECT Prefix || '8-10 days', Days8_10 FROM r
It will not double count records for the Total row. Since your day ranges overlap you cannot sum up the individual counts to get the total. As another query given here gives a total of 25 with only 20 records and 1 out of range.
The result for total is what you expect with 20 records and 1 being 12 days old. The innermost query does all the heavy lifting but it is executed once to get all aging results. Its result will be at most 11 rows, 0-10 days. The rest of the queries are for final results and pretty output.
You can eliminate one query level by SUMing one level in, I just find it easier to validate the results by being able to select intermediate queries for a spot check.
Here is the result of the query:
This approach allows you to maintain your buckets separately from your main SQL in case you want them to be different sizes or to name them something that is not generated from the SQL, such as 'On time', 'Delinquent', etc. and also provides a very readable main SQL block.
with aging as
(select count(*) count_per_day, (trunc(sysdate) - trunc(f.due_date)) age
from files_to_submit f
where trunc(f.due_date - 10) <= sysdate
group by (trunc(sysdate) - trunc(f.due_date))),
buckets as
(select 1 bucket_id, 0 bucket_min, 2 bucket_max, 'aging file to submit 0-2' bucket_name from dual
union select 2, 2, 4, 'aging file to submit 2-4' from dual
union select 3, 4, 6, 'aging file to submit 4-6' from dual
union select 4, 6, 8, 'aging file to submit 6-8' from dual
union select 5, 8, 10, 'aging file to submit 8-10' from dual
union select 6, null, null, 'aging file to submit total' from dual
)
select nvl(b.bucket_name, (select bucket_name from buckets where bucket_id = 6)), sum(a.count_per_day) bucket_cnt
from aging a
join buckets b on (a.age >= b.bucket_min and a.age <= b.bucket_max)
group by rollup(b.bucket_name)
order by b.bucket_name nulls first;
I have a question which is divided in two parts
Part 1
How can I get the following set of records with sysdate as current week?
07-Apr-2013 - 13-Apr-2013
14-Apr-2013 - 20-Apr-2013
21-Apr-2013 - 27-Apr-2013
28-Apr-2013 - 04-May-2013
If week is past 07-Apr-2012 - 13-Apr-2013, then next four sets. So always it will have 4 weeks.
Part 2
and if current week falls within the range of dates i.e. 07-Apr-2012 - 13-Apr-2013, I would like to get Monday and Friday from the list.
How can I get the desired output?
I'm a little confused by the date ranges you provide in your example as the start date of each range is a Sunday in 2013 yet you show 2012 as the year. I am going to assume the 2012 is a typo.
Does this get you what you want?
select
case
when trunc(sysdate) between start_date and end_date
then to_char(start_date + 1, 'DD-MON-YYYY')
else to_char(start_date, 'DD-MON-YYYY')
end
|| ' - ' ||
case
when trunc(sysdate) between start_date and end_date
then to_char(end_date - 1, 'DD-MON-YYYY')
else to_char(end_date, 'DD-MON-YYYY')
end date_range
from
(
select
next_day(trunc(sysdate - 7 + ((level - 1) * 7)), 'SUN') start_date,
next_day(trunc(sysdate) + ((level - 1) * 7), 'SAT') end_date
from dual
connect by level < 5
)
If you want just the 4 weeks then you can do this
select
to_char(next_day(trunc(sysdate - 7 + ((level - 1) * 7)), 'SUN'), 'DD-MON-YYYY')
|| ' - ' ||
to_char(next_day(trunc(sysdate) + ((level - 1) * 7), 'SAT'), 'DD-MON-YYYY') date_range
from dual
connect by level < 5
Part 1 (4 weeks starting with the current week)
SELECT TO_CHAR(trunc(SYSDATE, 'DY')) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 6) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+7) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 13) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+14) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 20) from dual
UNION
SELECT TO_CHAR(trunc(SYSDATE, 'DY')+21) || ' - ' || TO_CHAR(trunc(SYSDATE, 'DY')+ 27) from dual
;
Part 2 Monday and Friday of the current week:
SELECT trunc(SYSDATE, 'DY')+1 "Monday", trunc(SYSDATE, 'DY')+5 "Friday"
FROM dual;
Here's SQL Fiddle.
select
max(trunc(sysdate) + level - 7) as sunday,
max(trunc(sysdate) + level - 2) as friday,
max(trunc(sysdate) + level - 1) as saturday
from dual
connect by level < 30
group by to_char(sysdate + level, 'iw')
having max(trunc(sysdate) + level - 1) <= sysdate + 27
order by 1
fiddle