Need to assign a value to string in Oracle - oracle

I want to assign a value to string column. Below is the column contains the leave and working day data of one month.
Holiday_list (Column name)
--------------------------------------------------
WHHHHHHHWHHHHHHHWHHHHHHHWHHHHH
I want to know what are all the dates are working day and holiday in the list.

You can use a recursive sub-query factoring clause and SUBSTR:
WITH holidays ( column_name, dt, is_working, lvl ) AS (
SELECT column_name,
TRUNC( SYSDATE, 'MM' ), -- Replace with the start date for your list
SUBSTR( column_name, 1, 1 ),
1
FROM holiday_list
UNION ALL
SELECT column_name,
dt + INTERVAL '1' DAY,
SUBSTR( column_name, lvl + 1, 1 ),
lvl + 1
FROM holidays
WHERE lvl < LENGTH( column_name )
)
SELECT dt,
is_working
FROM holidays;
Which, for your sample data:
CREATE TABLE Holiday_list (Column_name) AS
SELECT 'WHHHHHHHWHHHHHHHWHHHHHHHWHHHHH' FROM DUAL;
Outputs:
DT | IS_WORKING
:------------------ | :---------
2021-03-01 00:00:00 | W
2021-03-02 00:00:00 | H
2021-03-03 00:00:00 | H
2021-03-04 00:00:00 | H
2021-03-05 00:00:00 | H
2021-03-06 00:00:00 | H
2021-03-07 00:00:00 | H
2021-03-08 00:00:00 | H
2021-03-09 00:00:00 | W
2021-03-10 00:00:00 | H
2021-03-11 00:00:00 | H
2021-03-12 00:00:00 | H
2021-03-13 00:00:00 | H
2021-03-14 00:00:00 | H
2021-03-15 00:00:00 | H
2021-03-16 00:00:00 | H
2021-03-17 00:00:00 | W
2021-03-18 00:00:00 | H
2021-03-19 00:00:00 | H
2021-03-20 00:00:00 | H
2021-03-21 00:00:00 | H
2021-03-22 00:00:00 | H
2021-03-23 00:00:00 | H
2021-03-24 00:00:00 | H
2021-03-25 00:00:00 | W
2021-03-26 00:00:00 | H
2021-03-27 00:00:00 | H
2021-03-28 00:00:00 | H
2021-03-29 00:00:00 | H
2021-03-30 00:00:00 | H
Or, if you want them all in a single row:
SELECT SUBSTR( column_name, 1, 1 ) AS day01,
SUBSTR( column_name, 2, 1 ) AS day02,
SUBSTR( column_name, 3, 1 ) AS day03,
SUBSTR( column_name, 4, 1 ) AS day04,
SUBSTR( column_name, 5, 1 ) AS day05,
SUBSTR( column_name, 6, 1 ) AS day06,
SUBSTR( column_name, 7, 1 ) AS day07,
SUBSTR( column_name, 8, 1 ) AS day08,
SUBSTR( column_name, 9, 1 ) AS day09,
SUBSTR( column_name, 10, 1 ) AS day10,
SUBSTR( column_name, 11, 1 ) AS day11,
SUBSTR( column_name, 12, 1 ) AS day12,
SUBSTR( column_name, 13, 1 ) AS day13,
SUBSTR( column_name, 14, 1 ) AS day14,
SUBSTR( column_name, 15, 1 ) AS day15,
SUBSTR( column_name, 16, 1 ) AS day16,
SUBSTR( column_name, 17, 1 ) AS day17,
SUBSTR( column_name, 18, 1 ) AS day18,
SUBSTR( column_name, 19, 1 ) AS day19,
SUBSTR( column_name, 20, 1 ) AS day20,
SUBSTR( column_name, 21, 1 ) AS day21,
SUBSTR( column_name, 22, 1 ) AS day22,
SUBSTR( column_name, 23, 1 ) AS day23,
SUBSTR( column_name, 24, 1 ) AS day24,
SUBSTR( column_name, 25, 1 ) AS day25,
SUBSTR( column_name, 26, 1 ) AS day26,
SUBSTR( column_name, 27, 1 ) AS day27,
SUBSTR( column_name, 28, 1 ) AS day28,
SUBSTR( column_name, 29, 1 ) AS day29,
SUBSTR( column_name, 30, 1 ) AS day30,
SUBSTR( column_name, 31, 1 ) AS day31
FROM holiday_list
Which outputs:
DAY01 | DAY02 | DAY03 | DAY04 | DAY05 | DAY06 | DAY07 | DAY08 | DAY09 | DAY10 | DAY11 | DAY12 | DAY13 | DAY14 | DAY15 | DAY16 | DAY17 | DAY18 | DAY19 | DAY20 | DAY21 | DAY22 | DAY23 | DAY24 | DAY25 | DAY26 | DAY27 | DAY28 | DAY29 | DAY30 | DAY31
:---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | :----
W | H | H | H | H | H | H | H | W | H | H | H | H | H | H | H | W | H | H | H | H | H | H | H | W | H | H | H | H | H | null
db<>fiddle here

If the only input is a string of 30 letters like you show in your Question, then it's meaningless. The first letter is W, but what date does it correspond to?
In the example below, I assume that your input has two columns - one shows "month" and the other the string of W and H as in your Question. I chose March 2021, on purpose, to illustrate an issue with your arrangement: the month has 31 days, but your string only has 30 letters. So, is March 31 a work day or a holiday?
The output of the query below is the same as in MT0's answer. The query itself is different. The with clause simulates your data (your table) - it is not part of the query you would run. Instead, the main select statement would reference your actual table and columns in that table.
with holidays as (
select 'March 2021' as mth, 'WHHHHHHHWHHHHHHHWHHHHHHHWHHHHH' as holiday_list
from dual
)
select to_date(mth, 'Month yyyy', 'nls_date_language=English') + level - 1 as dt,
substr(holiday_list, level, 1) as is_working_day
from holidays
connect by level <= length(holiday_list)
;

Related

Oracle sql set end date based on previous start date

I have one table where I need to add new column endDate for future implementation but since we have currently only start date for all records I need to set endDate which should be equal to start date from previous record that are connected by userId and if it is only one record for that user than end date will have some value in future.
For example:
Table structure:
ID | USER_ID | START_DATE | END_DATE
-------------------------------------
1 | 1 | 01.01.2015 |
2 | 1 | 01.01.2016 |
3 | 1 | 01.07.2018 |
4 | 1 | 01.08.2021 |
5 | 2 | 01.01.2015 |
6 | 3 | 01.01.2016 |
7 | 3 | 01.07.2018 |
8 | 4 | 01.08.2021 |
Expected result should be like this
ID | USER_ID | START_DATE | END_DATE
-------------------------------------
1 | 1 | 01.01.2015 | 01.01.2016
2 | 1 | 01.01.2016 | 01.07.2018
3 | 1 | 01.07.2018 | 01.08.2021
4 | 1 | 01.08.2021 | 01.01.2050
5 | 2 | 01.01.2015 | 01.01.2050
6 | 3 | 01.01.2016 | 01.07.2018
7 | 3 | 01.07.2018 | 01.01.2050
8 | 4 | 01.08.2021 | 01.01.2050
Can someone help me with how query in oracle databse should look to update it like this?
I've tried something with for loop but not sure how to continue from this step
DECLARE
CURSOR c_contract
IS
SELECT
USER_ID
FROM
CONTRACT
ORDER_BY START_DATE

BEGIN
FOR r_contract IN c_contract
LOOP

dbms_output.put_line( r_contract.USER_ID );
END LOOP;

END;
Use the LEAD analytic function with the default date as the third argument:
SELECT t.*,
LEAD( start_date, 1, DATE '2050-01-01') OVER (
PARTITION BY user_id
ORDER BY start_date
) AS end_date
FROM table_name t
Which, for the sample data:
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
CREATE TABLE table_name ( ID, USER_ID, START_DATE ) AS
SELECT 1, 1, DATE '2015-01-01' FROM DUAL UNION ALL
SELECT 2, 1, DATE '2016-01-01' FROM DUAL UNION ALL
SELECT 3, 1, DATE '2018-07-01' FROM DUAL UNION ALL
SELECT 4, 1, DATE '2021-08-01' FROM DUAL UNION ALL
SELECT 5, 2, DATE '2015-01-01' FROM DUAL UNION ALL
SELECT 6, 3, DATE '2016-01-01' FROM DUAL UNION ALL
SELECT 7, 3, DATE '2018-07-01' FROM DUAL UNION ALL
SELECT 8, 4, DATE '2021-08-01' FROM DUAL;
Outputs:
ID
USER_ID
START_DATE
END_DATE
1
1
2015-01-01 00:00:00
2016-01-01 00:00:00
2
1
2016-01-01 00:00:00
2018-07-01 00:00:00
3
1
2018-07-01 00:00:00
2021-08-01 00:00:00
4
1
2021-08-01 00:00:00
2050-01-01 00:00:00
5
2
2015-01-01 00:00:00
2050-01-01 00:00:00
6
3
2016-01-01 00:00:00
2018-07-01 00:00:00
7
3
2018-07-01 00:00:00
2050-01-01 00:00:00
8
4
2021-08-01 00:00:00
2050-01-01 00:00:00
If you want to add a column then:
ALTER TABLE table_name ADD (end_date DATE);
MERGE INTO table_name dst
USING (
SELECT ROWID AS rid,
LEAD( start_date, 1, DATE '2050-01-01') OVER (
PARTITION BY user_id
ORDER BY start_date
) AS end_date
FROM table_name
) src
ON (dst.ROWID = src.rid)
WHEN MATCHED THEN
UPDATE SET end_date = src.end_date;
fiddle

How to Convert From one currency into another in Oracle query

I am selecting filial expenditures in US dollar for a particular date. But I need to convert it into Won currency for that date. Currencies`s value changes at any time according to US dollar. Currency history is in table of V_CURRENCY. I need to multiply dollar to that amount and show in Won. My query is below and giving an error. Error is [22008][1861] ORA-01861. Mismatch of rows.
with cte as (
select t.filial_code,
t.modified_by as emp_code,
sum(t.sum_oper) as summa,
to_char(t.oper_date, 'YYYY-MM-DD') as operation_date
from OPERS t,
DEP_OPERS d
WHERE
And t.modified_by = 213
And t.filial_code = '00116'
And d.currency_code = 840
And t.oper_date >= to_date('07.01.2020', 'DD.MM.YYYY')
And t.oper_date < to_date('11.01.2020', 'DD.MM.YYYY')
group by to_char(t.oper_date, 'YYYY-MM-DD'), t.filial_code, t.modified_by
) select cte.filial_code,cte.emp_code,cte.summa * (select equival from V_CURRENCY
where date_activ = (select max(date_activ)
from V_CURRENCY
where date_activ <= cte.operation_date) and code = 840) as summa,cte.operation_date from cte;
From cte I am taking below result :
FILIAL_CODE | EMP_CODE | SUMMA | OPERATION_DATE
-----------------------------------------------
00116 | 213 | 40000 | 2020-01-14
00116 | 213 | 6000 | 2020-01-10
00116 | 213 | 2800 | 2020-01-06
My V_CURRENCY table is like below:
CODE | DATE_ACTIV | EQUIVAL|
--------------------------------
840 | 2020-01-13 00:00:00 | 576.97
840 | 2020-01-07 00:00:00 | 2008.54
840 | 2020-01-06 00:00:00 | 1941.91
840 | 2019-12-22 00:00:00 | 301.62
190 | 2020-01-13 00:00:00 | 1200.97
270 | 2020-01-13 00:00:00 | 2300.21
800 | 2019-12-22 00:00:00 | 100.62
I need to multiply equival from table V_CURRENCY in date 2020-01-13 00:00:00 to my cte result SUMMA for OPERATION_DATE 2020-01-14, means that 4000 * 576.97, cause OPERATION_DATE is closest one to currency change date. But when DATE_ACTIV exists for date 2020-01-06 then 2800 * 1941.91. I only need curreny value whose code is 840.
My last result should look like :
FILIAL_CODE | EMP_CODE | SUMMA | OPERATION_DATE
-----------------------------------------------
00116 | 213 | 40000 * 576.97 | 2020-01-14
00116 | 213 | 6000 * 2008.54 | 2020-01-10
00116 | 213 | 2800 * 1941.91 | 2020-01-06
Any response appreciated. Thanks in advance.
Use the LEAD analytic function to find the date the currency conversion is valid up until and then join the tables on the range between the start and end dates the currency is valid for:
SELECT y.filial_code,
y.emp_code,
y.summa * c.equival AS summa,
y.operation_date
FROM your_cte y
INNER JOIN (
SELECT c.*,
LEAD( DATE_ACTIV, 1, SYSDATE )
OVER ( PARTITION BY code ORDER BY date_activ )
AS DATE_FINISHED
FROM v_currency c
WHERE currency_code = 840
) c
ON ( y.operation_date >= c.date_activ
AND y.operation_date < c.date_finished )
Outputs:
FILIAL_CODE | EMP_CODE | SUMMA | OPERATION_DATE
:---------- | -------: | -------: | :-------------
00116 | 213 | 23078800 | 14-JAN-20
00116 | 213 | 12051240 | 10-JAN-20
00116 | 213 | 5437348 | 06-JAN-20
db<>fiddle here
As an aside, your CTE doesn't need to convert dates to strings and can use date literals and a modern ANSI join (rather than legacy comma join):
with cte ( filial_code, emp_code, summa, operation_date ) as (
SELECT t.filial_code,
t.modified_by,
sum(t.sum_oper),
t.oper_date
from OPERS t
CROSS JOIN
DEP_OPERS d
WHERE t.modified_by = 213
AND t.filial_code = '00116'
AND d.currency_code = 840
AND t.oper_date >= DATE '2020-01-07'
AND t.oper_date < DATE '2020-01-11'
GROUP BY t.oper_date,
t.filial_code,
t.modified_by
)
...
and you don't even need the CTE:
SELECT t.filial_code,
t.modified_by AS emp_code,
SUM(t.sum_oper * c.equival) AS summa,
t.oper_date AS operation_date
FROM OPERS t
CROSS JOIN
DEP_OPERS d
INNER JOIN (
SELECT c.*,
LEAD( DATE_ACTIV, 1, SYSDATE )
OVER ( PARTITION BY code ORDER BY date_activ )
AS DATE_FINISHED
FROM v_currency c
) c
ON ( t.oper_date >= c.date_activ
AND t.oper_date < c.date_finished
AND d.currency_code = c.currency_code )
WHERE t.modified_by = 213
AND t.filial_code = '00116'
AND d.currency_code = 840
AND t.oper_date >= DATE '2020-01-07'
AND t.oper_date < DATE '2020-01-11'
GROUP BY t.oper_date,
t.filial_code,
t.modified_by

How to get latest active record

Here is my data. Member can be enroll multiple times and can change plan anytime,I need to get C_level data for latest near to getdate that is "8/1/2017" for ID 1, For ID 2 doesn't have latest data, that case we have to show 12/31/2016 record.
ID Start_Date End_Date C_Level
1 1/1/2016 12/31/2016 1
1 1/1/2017 8/1/2017 2
1 9/1/2017 12/31/2017 3
1 1/1/2018 12/31/2018 0
2 1/1/2015 12/31/2015 2
2 1/1/2016 12/31/2016 3
If I understand your requirements right, then this query should give what you want:
WITH current_running AS (
SELECT to_date( '8/1/2017','mm/dd/rrrr') As Current_running_date
FROM dual
)
SELECT * FROM (
SELECT t.*,
row_number() Over (partition by id order by end_date desc ) As rn,
c.Current_running_date
FROM Table1 t
JOIN current_running c
ON c.Current_running_date >= ANY( t.Start_Date, t.End_Date )
)
WHERE rn = 1
;
Demo: http://sqlfiddle.com/#!4/33de0/10
For current_running_date = 2017-08-01 it gives:
| ID | START_DATE | END_DATE | C_LEVEL | RN | CURRENT_RUNNING_DATE |
|----|-----------------------|-----------------------|---------|----|----------------------|
| 1 | 2017-01-01 00:00:00.0 | 2017-08-01 00:00:00.0 | 2 | 1 | 2017-08-01T00:00:00Z |
| 2 | 2016-01-01 00:00:00.0 | 2016-12-31 00:00:00.0 | 3 | 1 | 2017-08-01T00:00:00Z |
while for current_running_date = 2016-07-15
| ID | START_DATE | END_DATE | C_LEVEL | RN | CURRENT_RUNNING_DATE |
|----|-----------------------|-----------------------|---------|----|----------------------|
| 1 | 2016-01-01 00:00:00.0 | 2016-12-31 00:00:00.0 | 1 | 1 | 2016-07-15T00:00:00Z |
| 2 | 2016-01-01 00:00:00.0 | 2016-12-31 00:00:00.0 | 3 | 1 | 2016-07-15T00:00:00Z |

List all days between two dates in Oracle

I am converting a postgres app to an Oracle app.
I came across this query:
WITH cost AS (SELECT
well_schedules.id,
generate_series(well_schedules.start_date::timestamp, well_schedules.end_date, '1 Day') AS "Date",
(well_schedules.drilling_engineering_estimate * well_schedules.well_estimated_working_interest)/((well_schedules.end_date - well_schedules.start_date) + 1) AS "Cost Per Day"
FROM
well_schedules
)
SELECT date_trunc('quarter', "Date"), COUNT("Cost Per Day"), id
FROM cost
GROUP BY id, date_trunc('quarter', "Date")
ORDER BY date_trunc('quarter', "Date")
The part I am struggling with is the generate_series line.
That line takes a start_date and end_date and lists all days between those two dates. We need that information to compile per day/week/month/quarter/year reports (or at least we assume we need that info).
Our data looks like this:
well_schedules
| id | start_date | end_date | cost |
| 1 | '2015-01-01' | '2015-03-20' | 100 |
We assume cost_per_day is equal across all days, so we'd like to generate a report that lets us look at cost_per_day, cost_per_week, cost_per_month, cost_per_year, and cost_per_quarter. cost_per_week/month/quarter/year is calculated by grouping the days by week/month/quarter/year and summing the associated cost_per_days
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE well_schedules ( id, start_date, end_date, cost ) AS
SELECT 1 , DATE '2015-01-01', DATE '2015-01-20', 100 FROM DUAL;
Query 1:
SELECT ID,
COLUMN_VALUE AS Day,
COST / ( end_date - start_date + 1 ) AS Cost_per_day
FROM well_schedules,
TABLE (
CAST(
MULTISET(
SELECT start_date + LEVEL - 1
FROM DUAL
CONNECT BY start_date + LEVEL - 1 <= end_date
)
AS SYS.ODCIDATELIST
)
)
Results:
| ID | DAY | COST_PER_DAY |
|----|---------------------------|--------------|
| 1 | January, 01 2015 00:00:00 | 5 |
| 1 | January, 02 2015 00:00:00 | 5 |
| 1 | January, 03 2015 00:00:00 | 5 |
| 1 | January, 04 2015 00:00:00 | 5 |
| 1 | January, 05 2015 00:00:00 | 5 |
| 1 | January, 06 2015 00:00:00 | 5 |
| 1 | January, 07 2015 00:00:00 | 5 |
| 1 | January, 08 2015 00:00:00 | 5 |
| 1 | January, 09 2015 00:00:00 | 5 |
| 1 | January, 10 2015 00:00:00 | 5 |
| 1 | January, 11 2015 00:00:00 | 5 |
| 1 | January, 12 2015 00:00:00 | 5 |
| 1 | January, 13 2015 00:00:00 | 5 |
| 1 | January, 14 2015 00:00:00 | 5 |
| 1 | January, 15 2015 00:00:00 | 5 |
| 1 | January, 16 2015 00:00:00 | 5 |
| 1 | January, 17 2015 00:00:00 | 5 |
| 1 | January, 18 2015 00:00:00 | 5 |
| 1 | January, 19 2015 00:00:00 | 5 |
| 1 | January, 20 2015 00:00:00 | 5 |
I will suggest the code below that consider the first and last day of the month from two dates:
Example:
Date Initial: 01/10/2014
Date Final: 12/21/2018
The code will return:
01/01/2014
02/01/2014
03/01/2014
04/01/2014
...
12/28/2018
12/29/2018
12/30/2018
12/31/2018
The Code:
SELECT
CAL.DT AS "Date"
,TO_NUMBER(TO_CHAR(CAL.DT,'DD')) AS "Day"
,TO_NUMBER(TO_CHAR(CAL.DT,'MM')) AS "Month"
,TO_NUMBER(TO_CHAR(CAL.DT,'YY')) AS "YearYY"
,TO_NUMBER(TO_CHAR(CAL.DT,'YYYY')) AS "YearYYYY"
,TO_CHAR(CAL.DT,'day') AS "Description_Day"
,TO_CHAR(CAL.DT,'dy') AS "Description_Day_Abrev"
,TO_CHAR(CAL.DT,'Month') AS "Description_Month"
,TO_CHAR(CAL.DT,'Mon') AS "Description_Month_Abrev"
,TO_CHAR(CAL.DT,'dd month yyyy') AS "Date_Text"
FROM (
SELECT
(
TO_DATE(SEQ.MM || SEQ.YYYY, 'MM/YYYY')-1
) + SEQ.NUM AS "DT"
FROM
(
SELECT RESULT NUM,
TO_CHAR(( -- Minimum Date
TO_DATE('01/01/2014', 'DD/MM/YYYY')
) , 'MM') AS "MM",
TO_CHAR(( -- Minimum Date
TO_DATE('01/01/2014', 'DD/MM/YYYY')
) , 'YYYY') AS "YYYY"
FROM
(
SELECT ROWNUM RESULT FROM DUAL CONNECT BY LEVEL <= (
(
-- Maximum Date
LAST_DAY(TO_DATE('31/12/2018', 'DD/MM/YYYY')) -- Always Last Day
-
-- Maximum Date
TRUNC(TO_DATE('01/01/2014', 'DD/MM/YYYY')) -- Always First Day of Month
) + 1 -- Because the First Day (RESULT) don't begin at zero
)
) -- How many sequences (RESULT) to generate
) SEQ
) CAL
;

ORACLE: INSERT SELECT FROM 2 views and value from param

I'm trying to insert some fields into MYTABLE from views MYVIEW1 and MYVIEW2 and then add a value from a parameter (this is part of a stored procedure) for UPDATED_BY, SYSDATE for UPDATED_ON. How can I correctly do this with INSERT SELECT or some other way entirely?
MYVIEW1
+------+----+-----+-----------+---------+
| YR | MO | QTR | USER_CODE | MO_PERF |
+------+----+-----+-----------+---------+
| 2012 | 1 | 1 | 1099 | 89 |
| 2012 | 2 | 1 | 1099 | 86 |
| 2012 | 3 | 1 | 1099 | 95 |
+------+----+-----+-----------+---------+
MYVIEW2
+------+-----+-----------+----------+
| YR | QTR | USER_CODE | QTR_PERF |
+------+-----+-----------+----------+
| 2012 | 1 | 1099 | 90 |
+------+-----+-----------+----------+
MYTABLE
+------+-----+-----------+---------+---------+---------+---------+-------------+------------+
| YR | QTR | USER_CODE | MO1_PCT | MO2_PCT | MO3_PCT | INC | UPDATED_BY | UPDATED_ON |
+------+-----+-----------+---------+---------+---------+---------+-------------+------------+
| 2012 | 1 | 1099 | 89 | 86 | 95 | 7000 | SAMPLE NAME | 01/16/2013 |
+------+-----+-----------+---------+---------+---------+---------+-------------+------------+
INSERT INTO MYTABLE
(YR,QTR,USER_CODE,MO1_PCT,MO2_PCT,MO3_PCT,INC,UPDATED_BY,UPDATED_ON)
SELECT b.YR,b.QTR,b.USER_CODE,b.MO1_PCT,b.MO2_PCT,b.MO3_PCT,c.INC
FROM MYVIEW1 b,
MYVIEW2 c
How do I insert values for (first month of QTR's MO_PERF) as MO1_PCT and (second month of QTR's MO_PERF) as MO2_PCT and (last month of QTR's MO_PERF) as MO3_PCT, making sure that I've inserted the right month within the right quarter and year.And then check if the MO_PERF values of each month has reached at least 85, else set INC as NULL.
,CASE WHEN MO1_PCT>=85 AND MO2_PCT>=85 AND MO3_PCT>=85 THEN 7000
ELSE NULL
END INC
If you're using oracle 11g then you can use PIVOT like this:
select YR, QTR, USER_CODE, "1_MO_PCT" MO1_PCT, "2_MO_PCT" MO2_PCT, "3_MO_PCT" MO3_PCT ,
case when "1_MO_PCT" >= 85 and "2_MO_PCT" >= 85 and "2_MO_PCT" >= 85 then 7000 end INC,
user updated_by, sysdate updated_on
from (
select m1.yr, m1.mo, m1.qtr, m1.user_code, m1.mo_perf, m2.qtr_perf
from myview1 m1 join myview2 m2 on m1.yr=m2.yr
and m1.qtr = m2.qtr and m1.user_code = m2.user_code )t
pivot(
max(mo_perf) MO_PCT for mo in (1,2,3)
)
Here is a sqlfiddle demo

Resources