How to display the days in 1 week in oracle? - oracle

I'm stuck, please help me how to display the cover days (e.g Monday, Tuesday, etc) per week. Please help me. Thank you!
Desired Sample Output:
Data,03/24/2014,Monday,20,Tuesday,30.....
Data,03/31/2014,Monday,12,Tuesday,20.....
Here's my script:
select 'Data'
||','||to_char(d.dtime_day, 'MM/dd/yyyy')
||','||nvl(g.total, 0)
from tablename d
left join (
select trunc(t.create_time, 'IW') as ddate
,count(t.create_time) as total
from tablename1 t
left join tablename2 q
on q.id = t.queue_id
where t.create_time between trunc(sysdate,'IW')-12*7 and sysdate -1
and q.name not like 'Data1%'
or q.name not like 'Data2%'
or q.name not like 'Data3%'
or q.name not like 'Data4%'
or q.name not like 'Data5%'
or q.name not like 'Data6%'
or q.name not like 'Data7%'
or q.name not like 'Data8%'
or q.name not like 'Data9%'
group by trunc(t.create_time, 'IW')
) g on d.dtime_day = g.ddate
where d.dtime_day between trunc(sysdate,'IW')-12*7 and trunc(sysdate) -1
and trunc(d.dtime_day, 'IW')= d.dtime_day
order by d.dtime_day;
Output of the script:
Data,03/24/2014,42
Data,03/31/2014,25

You can also select the day of the week using to_char e.g.
select to_char(sysdate, 'Day') from dual;

Used in Oracle Apex for a LOV in a Form
select basic_day display, basic_day return
from
(select trim(to_char(basic_date, 'DAY')) basic_day
from
( select 7 my_row, trunc(sysdate, 'DAY') basic_date
from dual
union
select 1, trunc(sysdate, 'DAY') + 1
from dual
union
select 2, trunc(sysdate, 'DAY') + 2
from dual
union
select 3, trunc(sysdate, 'DAY') + 3
from dual
union
select 4, trunc(sysdate, 'DAY') + 4
from dual
union
select 5, trunc(sysdate, 'DAY') + 5
from dual
union
select 6, trunc(sysdate, 'DAY') + 6
from dual)
order by my_row
)

Related

how to get last businessday of last month in oralce

I have data like this my table
2020-01-01 H
2020-01-02 B
2020-01-03 B
2020-01-04 B
.
2020-01-29 B
2020-01-30 H
2020-01-31 H
2020-01-02 H
2020-02-02 H
2020-02-03 B
2020-02-04 B
2020-02-05 B
.
now my problem is in the current month i need to check third business day i.e in this case 2020-02-05 i need to get last business day of last month. i.e.2020-01-29
By adding 2 columns:
row_number() over(partition by trunc(date_value,'MM'), day_type order by date_value) as rn_month_asc,
row_number() over(partition by trunc(date_value,'MM'), day_type order by date_value desc) as rn_month_desc
in a month the 3rd business day will have rn_month_asc=3 and day_type ='B' and the latest business day will have rn_month_desc=1 and day_type ='B', and easy to query other situations if you need to.
in the current month I need to check third business day
From Oracle 12, you can use:
SELECT date_value
FROM table_name
WHERE TRUNC(SYSDATE, 'MM') <= date_value
AND date_value < ADD_MONTHS(TRUNC(SYSDATE, 'MM'), 1)
AND day_type = 'B'
ORDER BY date_value ASC
OFFSET 2 ROWS
FETCH NEXT ROW ONLY;
Which, for the sample data:
CREATE TABLE table_name (date_value, day_type) AS
SELECT DATE '2020-01-01', 'H' FROM DUAL UNION ALL
SELECT DATE '2020-01-02', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-03', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-04', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-05', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-28', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-29', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-01-30', 'H' FROM DUAL UNION ALL
SELECT DATE '2020-01-31', 'H' FROM DUAL UNION ALL
SELECT DATE '2020-01-02', 'H' FROM DUAL UNION ALL
SELECT DATE '2020-02-02', 'H' FROM DUAL UNION ALL
SELECT DATE '2020-02-03', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-02-04', 'B' FROM DUAL UNION ALL
SELECT DATE '2020-02-05', 'B' FROM DUAL;
If the current month was 2020-01 then the output is:
DATE_VALUE
04-JAN-20
I need to get last business day of last month
SELECT date_value
FROM table_name
WHERE ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1) <= date_value
AND date_value < TRUNC(SYSDATE, 'MM')
AND day_type = 'B'
ORDER BY date_value DESC
FETCH FIRST ROW ONLY;
If the current month is 2020-02 then the output is:
DATE_VALUE
29-JAN-20
fiddle

Concatenated Select List value returns 'not a valid month' when applied TO_DATE

I have month and year values from select list, concatenated them in a string. If TO_DATE is applied on the string, that returns 'not a valid month' error.
Below is my code snippet,
V_DATE_FROM_STR_TEST := TRIM('01-'||TRIM(TO_CHAR(:P3_FROM_MONTH))||'-'||TRIM(TO_CHAR(:P3_YEAR)));
V_DATE_TO_STR_TEST := TRIM('01-'||TRIM(TO_CHAR(:P3_TO_MONTH))||'-'||TRIM(TO_CHAR(:P3_YEAR)));
Error 'not a valid month' occurs on this line,
TRUNC(TO_DATE(V_DATE_FROM_STR_TEST, 'DD-MON-YYYY'))
I have tried printing by HTP.PRN(V_DATE_FROM_STR_TEST) that shows date 01-JAN-2020.
Adding LOVs
Month LOV
select to_char(add_months(trunc(sysdate, 'yyyy'), level - 1), 'MONTH') d,
to_char(add_months(trunc(sysdate, 'yyyy'), level - 1), 'MON') r
from dual
connect by level <= 12
Year LOV
select YEAR d, YEAR r
from (select to_number(to_char(sysdate,'yyyy')) -8 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -7 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -6 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -5 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -4 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -3 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -2 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) -1 YEAR
from dual
UNION
select to_number(to_char(sysdate,'yyyy')) YEAR
from dual
) order by year desc
I am guessing there are some unwanted character is added in the date string from select list value, how can I remove that?
If you switch to digits, things might improve.
Month LoV: display words, but return numbers:
select to_char(add_months(trunc(sysdate, 'yyyy'), level - 1), 'MONTH') d,
level r
from dual
connect by level <= 12;
Then use this for the resulting string:
to_date(lpad(:P3_FROM_MONTH, 2, '0') || :P3_YEAR, 'mmyyyy')
Also, all those TRIMs look unnecessary, but OK - I understand - you tried to fix the problem.
While not directly referenced you can simplify your "Year LOV" query.
select yr d, yr r
from ( select extract(year from sysdate)-level +1 yr
from dual
connect by level <= 9
)
order by yr desc;

oracle query to retrieve closest and second closest future date based on the current date

I want to retrieve the closest and second closest future date based on the current date.
example :
current-date=28-07-2017
dates to be retrieve
28-07-2017
29-07-2017
or followed top two dates which are closest to current date.
plzz help me out in writing this query in oracle
Try this:
select sysdate,sysdate + level "Dates" From DUAL connect by level <= 1 ;
You can do this by using the dense_rank analytic function, like so:
WITH sample_data AS (SELECT 1 ID, to_date('01/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 2 ID, to_date('02/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 3 ID, to_date('02/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 4 ID, to_date('03/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 5 ID, to_date('04/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 6 ID, to_date('05/07/2017', 'dd/mm/yyyy') dt FROM dual UNION ALL
SELECT 7 ID, to_date('06/07/2017', 'dd/mm/yyyy') dt FROM dual)
SELECT ID, dt
FROM (SELECT ID,
dt,
dense_rank() OVER (ORDER BY dt) dr
FROM sample_data
WHERE dt >= to_date('01/07/2017', 'dd/mm/yyyy'))
WHERE dr <= 2;
ID DT
---------- -----------
1 01/07/2017
2 02/07/2017
3 02/07/2017

How to query for a specific day of the month in Oracle

Trying to automate a query that will pull data for the current month where the day of the month (in the date field) is >= the 15th. Is this possible? If so, what is the syntax to achieve this?
I want to be able to run this query each month without having to change anything. So in May, it would automatically pull any item where the date was >= 5/15/16. In June, it would pull items where the date was >= 6/15/16. And so on.....
Any help in this would be greatly appreciated. Thanks
This will allow you to use any indexes you have on your date_field column:
SELECT *
FROM table_name
WHERE date_field >= TRUNC( SYSDATE, 'MM' ) + INTERVAL '14' DAY
AND date_field < ADD_MONTHS( TRUNC( SYSDATE, 'MM' ), 1 );
If your date/time fields are of type timestamp you can do
select x from <your_table>
where EXTRACT(DAY from <timestamp field>) >=15
and EXTRACT(MONTH from <timestamp field>) = EXTRACT(MONTH FROM CURRENT_TIMESTAMP)
and EXTRACT(YEAR from <timestamp field>) = EXTRACT(YEAR FROM CURRENT_TIMESTAMP);
I think what you're after is something like:
with sample_data as (select 1 id, to_date('01/06/2016', 'dd/mm/yyyy') dt from dual union all
select 2 id, to_date('10/06/2016', 'dd/mm/yyyy') dt from dual union all
select 3 id, to_date('14/06/2016', 'dd/mm/yyyy') dt from dual union all
select 4 id, to_date('15/06/2016', 'dd/mm/yyyy') dt from dual union all
select 5 id, to_date('16/06/2016', 'dd/mm/yyyy') dt from dual union all
select 6 id, to_date('30/06/2016', 'dd/mm/yyyy') dt from dual union all
select 7 id, to_date('01/07/2016', 'dd/mm/yyyy') dt from dual)
select *
from sample_data
where dt >= trunc(sysdate, 'mm') + 14
and dt < last_day(trunc(sysdate)) + 1;
ID DT
---------- ----------
4 15/06/2016
5 16/06/2016
6 30/06/2016
(If you wanted rows with any date greater than the 15th of the current month, then remove the last predicate in the where clause.)

Group 'n' rows in to columns - oracle

I have a situation where I need to split 'n' rows in to column group. For example, Below is dataset
COMMENT_TEXT
T1
T2
T3
T4
T5
T6
Expected Output:
SUN MON TUE
T1 T2 T3
T4 T5 T6
My Query:
SELECT htbp1.comment_text
FROM hxc_time_building_blocks htbp,
hxc_time_building_blocks htbp1
WHERE htbp1.parent_building_block_id = htbp.time_building_block_id
AND htbp1.parent_building_block_ovn = htbp.parent_building_block_ovn
AND htbp.parent_building_block_id = 116166
AND htbp.parent_building_block_ovn = 1
ORDER BY htbp1.time_building_block_id
Is there any way I can do PIVOT with a 'n' rows and without aggregate function?
Edit: T1/T2/T3 as sample data sets but in real it can be any random free text or null.
SELECT * FROM (SELECT htbp1.comment_text, TO_CHAR (htbp.start_time, 'DY') par_time,
trunc((rownum-1) / 7) buck
FROM hxc_time_building_blocks htbp,
hxc_time_building_blocks htbp1,
hxc_timecard_summary hts
WHERE hts.RESOURCE_ID = :p_resource_id
AND TRUNC(hts.STOP_TIME) = TRUNC(:p_wkend_date)
AND htbp1.parent_building_block_id = htbp.time_building_block_id
AND htbp1.parent_building_block_ovn = htbp.parent_building_block_ovn
AND htbp.parent_building_block_id = hts.timecard_id
AND htbp.parent_building_block_ovn = hts.timecard_ovn
ORDER BY htbp1.time_building_block_id ) PIVOT( max(comment_text) FOR par_time
IN ('SUN' AS "SUN",
'MON' AS "MON",
'TUE' AS "TUE",
'WED' AS "WED",
'THU' AS "THU",
'FRI' AS "FRI",
'SAT' AS "SAT"));
When I added the another table 'hxc_timecard_summary' which is parent then data is going crazy, but if I use the hardcoded parameters like the one in the first then the rows are showing up fine.
PIVOT also uses an aggregate function but you don't need a GROUP BY:
with tab as (
select sysdate - 7 date_col, 'T1' comment_text from dual
union all select sysdate - 6, 'T2' from dual
union all select sysdate - 5, 'T3' from dual
union all select sysdate - 4, 'T4' from dual
union all select sysdate - 3, 'T5' from dual
union all select sysdate - 2, 'T6' from dual
union all select sysdate - 1, 'T7' from dual
)
select * from (select to_char(date_col, 'D') day_of_week, comment_text from tab)
PIVOT (max(comment_text) for day_of_week in (7 as sun, 1 as mon, 2 as tue));
Also, I suppose you need the second column with a date to form your new columns.
And you cannot use expressions for FOR clause - this should be column(s). For example, this won't work:
select * from tab
PIVOT (max(comment_text) for to_char(date_col, 'D') in (7 as sun, 1 as mon, 2 as tue));
because of to_char(date_col, 'D')
Try using pivot.
It allows rows to be mapped to columns.
Its from 11g onwards I believe.
with tab as (
select 'T1' comment_text from dual
union all select 'T2' from dual
union all select 'T3' from dual
union all select 'T4' from dual
union all select 'T5' from dual
union all select 'T6' from dual
)
select regexp_substr(txt, '[^,]+', 1, 1) sun,
regexp_substr(txt, '[^,]+', 1, 2) mon,
regexp_substr(txt, '[^,]+', 1, 3) tue
from (
select buck, wm_concat(comment_text) txt
from (
select comment_text, trunc((rownum-1) / 3) buck
from (select comment_text from tab order by comment_text)
)
group by buck
);
wm_concat(comment_text) (Oracle 10g) =
listagg(comment_text, ',') within group(order by comment_text) (Oracle 11g)
But these two functions are both aggregate
My third try, no aggregate functions at all (works fine in Oracle 10g)
with tab as (
select 'T1' comment_text from dual
union all select 'T2' from dual
union all select 'T3' from dual
union all select 'T4' from dual
union all select 'T5' from dual
union all select 'T6' from dual
)
select regexp_substr(txt, '[^(#####)]+', 1, 1) sun,
regexp_substr(txt, '[^(#####)]+', 1, 2) mon,
regexp_substr(txt, '[^(#####)]+', 1, 3) tue
from (
select sys_connect_by_path(comment_text, '#####') txt, parent_id
from (
select rownum id, comment_text, mod(rownum-1, 3) parent_id
from (select comment_text from tab order by comment_text)
)
start with parent_id = 0
connect by prior id = parent_id
) where parent_id = 2;

Resources