Compare date time to another table date_time - sql

select uid , max(price) keep(dense_rank last order by usage_date ASC) amount
from HISTORY group by uid" ;
compare HISTORY to ADJUSTMENT
If the latest usage_date (each id ) is before (sen_date)
I would like to add the price of ADJUSTMENT
How can I do this ?
*I want to add the price of ADJUSTMENT to max(price) if usage_date is older than ADJUSTMENT
in this case uid= 5 is should be added 200
ADJUSTMENT
uid,price,sen_date
1,100,2020-10-23
2,200,2020-10-23
2,200,2020-09-22
2,200,2020-08-23
2,200,2020-10-22
3,300,2020-10-20
5,200,2020-10-20
HISTORY
uid,price,usage_date
1,1000,2020-10-23
1,1000,2020-10-19
1,1000,2020-10-03
2,1000,2020-10-23
3,1000,2020-10-23
3,1000,2020-10-23
3,1000,2020-10-23
4,1000,2020-10-20
4,1000,2020-10-23
4,1000,2020-10-19
4,1000,2020-10-23
4,1000,2020-10-23
5,1000,2020-10-02
5,1000,2020-10-03
5,1000,2020-10-04
6,1000,2020-10-23
7,1000,2020-10-23

Take your query and LEFT OUTER JOIN it to a similar query for the ADJUSTMENT table correlating on uid with a later date and then use COALESCE to combine the dates:
SELECT h."UID",
h.usage_date,
a.sen_date,
h.price AS base_price,
COALESCE( a.price, 0 ) AS price_adjustment,
h.price + COALESCE( a.price, 0 ) AS price
FROM (
SELECT "UID",
MAX( usage_date ) AS usage_date,
MAX(price) KEEP ( DENSE_RANK LAST ORDER BY usage_date ASC) AS price
FROM HISTORY
GROUP BY "UID"
) h
LEFT OUTER JOIN
(
SELECT "UID",
MAX( sen_date ) AS sen_date,
MAX(price) KEEP ( DENSE_RANK LAST ORDER BY sen_date ASC) AS price
FROM ADJUSTMENT
GROUP BY "UID"
) a
ON ( h."UID" = a."UID" AND h.usage_date < a.sen_date )
ORDER BY "UID"
Which, for the sample data:
CREATE TABLE adjustment ( "UID",price,sen_date ) AS
SELECT 1,100,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 2,200,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 2,200,DATE '2020-09-22' FROM DUAL UNION ALL
SELECT 2,200,DATE '2020-08-23' FROM DUAL UNION ALL
SELECT 2,200,DATE '2020-10-22' FROM DUAL UNION ALL
SELECT 3,300,DATE '2020-10-20' FROM DUAL UNION ALL
SELECT 5,200,DATE '2020-10-20' FROM DUAL;
CREATE TABLE HISTORY ( "UID",price,usage_date) AS
SELECT 1,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 1,1000,DATE '2020-10-19' FROM DUAL UNION ALL
SELECT 1,1000,DATE '2020-10-03' FROM DUAL UNION ALL
SELECT 2,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 3,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 3,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 3,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 4,1000,DATE '2020-10-20' FROM DUAL UNION ALL
SELECT 4,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 4,1000,DATE '2020-10-19' FROM DUAL UNION ALL
SELECT 4,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 4,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 5,1000,DATE '2020-10-02' FROM DUAL UNION ALL
SELECT 5,1000,DATE '2020-10-03' FROM DUAL UNION ALL
SELECT 5,1000,DATE '2020-10-04' FROM DUAL UNION ALL
SELECT 6,1000,DATE '2020-10-23' FROM DUAL UNION ALL
SELECT 7,1000,DATE '2020-10-23' FROM DUAL;
Outputs:
UID | USAGE_DATE | SEN_DATE | BASE_PRICE | PRICE_ADJUSTMENT | PRICE
--: | :--------- | :-------- | ---------: | ---------------: | ----:
1 | 23-OCT-20 | null | 1000 | 0 | 1000
2 | 23-OCT-20 | null | 1000 | 0 | 1000
3 | 23-OCT-20 | null | 1000 | 0 | 1000
4 | 23-OCT-20 | null | 1000 | 0 | 1000
5 | 04-OCT-20 | 20-OCT-20 | 1000 | 200 | 1200
6 | 23-OCT-20 | null | 1000 | 0 | 1000
7 | 23-OCT-20 | null | 1000 | 0 | 1000
db<>fiddle here

Do you just mean this (shown here)?
SELECT a.* FROM adjustment a
WHERE a.sen_date > (SELECT max(usage_date) FROM history WHERE uid = a.uid)

Related

Oracle Alpha-Numeric column sorting

I am working on to Sort the Revision column of an Oracle DB table in the asc order as per below.
At first the numeric revisions to be sorted (1,2,3,…).
Thereafter Alpha-Numeric to be sorted as following: A, B, B1, C, C1, C2,…,Y, Y2, Y3, Z, AA, AB,..,DA, …ZZ, etc.
Row_Number() in the SELECT statement to be filled with 1,2,3… for each document# (ABC, XYZ) after revision sorting out.
See the uploaded image for the required table.
I tried with SUBSTR , Order by, etc but failed to sort out as per above requirement.
Can someone help me on this ? Thanks!
As I understand your question, you want to put last revisions that contain only two characters and no digits.
You can use a conditional sort:
select
t.*,
row_number() over(
partition by doc#
order by
case when regexp_like(revision, '^\w\d?$') then 0 else 1 end,
revision
) rn
from t
order by doc#, rn
The regular expression describes a string starting with an alphanumeric character, optionally followed by a digit: these revisions should come first.
Demo on DB Fiddle:
with t as (
select 'ABC' doc#, '1' revision from dual
union all select 'ABC', '2' from dual
union all select 'ABC', '3' from dual
union all select 'ABC', 'A' from dual
union all select 'ABC', 'B' from dual
union all select 'ABC', 'B1' from dual
union all select 'ABC', 'C' from dual
union all select 'ABC', 'C1' from dual
union all select 'ABC', 'D' from dual
union all select 'ABC', 'AA' from dual
union all select 'ABC', 'AB' from dual
union all select 'ABC', 'BA' from dual
union all select 'ABC', 'DA' from dual
)
select
t.*,
row_number() over(
partition by doc#
order by
case when regexp_like(revision, '^\w\d?$') then 0 else 1 end,
revision
) rn
from t
order by doc#, rn
DOC# | REVISION | RN
:--- | :------- | -:
ABC | 1 | 1
ABC | 2 | 2
ABC | 3 | 3
ABC | A | 4
ABC | B | 5
ABC | B1 | 6
ABC | C | 7
ABC | C1 | 8
ABC | D | 9
ABC | AA | 10
ABC | AB | 11
ABC | BA | 12
ABC | DA | 13
There is well known old method: rpad(col, max-length, '0')
For example rpad(col, max(length(col)) over(), '0'

SQL: summing a column starting from row immediately after two consecutive 'trigger' values in another column

How to sum all values after two consecutive YES's in the CONDITION_SATISFIED column?
ID | CONDITION_SATISFIED | VALUE
--------------------------------
1 | NO | 100
2 | NO | 300
3 | NO | 500
4 | YES | 100
5 | YES | 300
6 | NO | 500 <-
7 | NO | 100 <-
8 | YES | 300 <-
9 | NO | 500 <-
--------------------------------
SUM | 1400
Note: further occurrences of YES/NO are ignored once the summation is started.
I've gotten to the point where I am able to generate two extra columns for the CONDITION_SATISFIED column like this:
ID | CONDITION_SATISFIED | VALUE RANK | REPEAT_COUNT
-------------------------------- -------------------
1 | NO | 100 1 | 3
2 | NO | 300 1 | 3
3 | NO | 500 1 | 3
4 | YES | 100 2 | 2
5 | YES | 300 2 | 2
6 | NO | 500 3 | 2 <- start from here
7 | NO | 100 3 | 2
8 | YES | 300 4 | 1
9 | NO | 500 5 | 1
-------------------------------- -------------------
But I'm not able to figure out how to get the first instance of REPEAT_COUNT >= 2 AND CONDITION_SATISFIED = 'YES', and then start the summation immediately after the 2nd YES (as indicated).
Hmmm . . . You can get the first where the two yesses are using lag():
select t.*
from (select t.*,
lag(condition_satisfied) over (order by id) as prev_cs,
lag(condition_satisfied, 2) over (order by id) as prev2_cs
from t
) t
where prev2_cs = 'YES' and prev_cs = 'YES';
Then you can just use this in a query:
select t.*
from t join
(select min(t.id) as id
from (select t.*,
lag(condition_satisfied) over (order by id) as prev_cs,
lag(condition_satisfied, 2) over (order by id) as prev2_cs
from t
) t
where prev2_cs = 'YES' and prev_cs = 'YES'
) yy
on t.id >= yy.id;
Oracle 12c: pattern matching
with t1 (id, condition_satisfied, value) as (
select 1, 'NO' , 100 from dual union all
select 2, 'NO' , 300 from dual union all
select 3, 'NO' , 500 from dual union all
select 4, 'YES', 100 from dual union all
select 5, 'YES', 300 from dual union all
select 6, 'NO' , 500 from dual union all
select 7, 'NO' , 100 from dual union all
select 8, 'YES', 300 from dual union all
select 9, 'NO' , 500 from dual)
select sum(v_value) as sum_value
from t1
match_recognize(
order by id
measures s.value as v_value
all rows per match
pattern (yes{2} s+)
define
yes as condition_satisfied = 'YES'
);
SUM_VALUE
----------
1400
If you have version lower than 12 no need to self-join and generate/prevent duplicates:
with s (id, condition_satisfied, value) as (
select 1, 'NO' , 100 from dual union all
select 2, 'NO' , 300 from dual union all
select 3, 'NO' , 500 from dual union all
select 4, 'YES', 100 from dual union all
select 5, 'YES', 300 from dual union all
select 6, 'NO' , 500 from dual union all
select 7, 'YES' , 100 from dual union all
select 8, 'YES', 300 from dual union all
select 9, 'NO' , 500 from dual)
select sum(value) sum_value
from
(select s.*, min(first_id) over () min_id
from
(select s.*,
case when condition_satisfied = 'YES' and condition_satisfied = lag(condition_satisfied) over (order by id) then id end first_id
from s
) s
)
where id > min_id;
SUM_VALUE
----------
1400

Oracle - count records if number of token less than 2

I have records like...
ID | KEY
-------|---------
1 | 123_456_abc
1 | 123_xyz
1 | 456_abc
2 | 123_abc
2 | 122_73_zcc
3 | 123_wer
4 | 345_23_fhd
4 | 3453_abc
5 | ad1fr2h3_abcasd
5 | ers2g45bb_abc2rtd
5 | asf23g_abc1_sf45
I want count(ID) where count(tokanize(numeric(KEY),'_')) < 2
As count(ID) will be 6
You can try something like this
SELECT COUNT(ID) FROM xyz WHERE key NOT LIKE '%_%_%';
This should filter all elements which have less than two underscores.
Try this :
select Count(1) from
(with abc(id,key) as (select '1','123_456_abc' from dual
Union all
select '1','123_xyz' from dual
UNion all
select '1','456_abc' from dual
Union all
select '2','123_abc' from dual
UNion all
select '2','123_73_zcc' from dual
Union all
select '3','123_wer' from dual
UNion all
select '1','345_23_fhd' from dual
UNion all
select '1','345_abc' from dual
)
select key, length(regexp_replace(key,'[^_]*','')) cntr
from abc )
where cntr = 1
eliminate all records which has more than 1 underscores
then eliminate the ones which do not start with a number
then sum it up
select sum(cnt) from (
select key, cnt, id from (
select key, length(regexp_replace(key,'[^_]*','')) cnt, id from table_name
) where cnt < 2
) where regexp_like(key,'[1-9]+(.)*')

Use SUM function in oracle

I have a table in Oracle which contains :
id | month | payment | rev
----------------------------
A | 1 | 10 | 0
A | 2 | 20 | 0
A | 2 | 30 | 1
A | 3 | 40 | 0
A | 4 | 50 | 0
A | 4 | 60 | 1
A | 4 | 70 | 2
I want to calculate the payment column (SUM(payment)). For (id=A month=2) and (id=A month=4), I just want to take the greatest value from REV column. So that the sum is (10+30+40+70)=150. How to do it?
You can also use below.
select id,sum(payment) as value
from
(
select id,month,max(payment) from table1
group by id,month
)
group by id
Edit: for checking greatest rev value
select id,sum(payment) as value
from (
select id,month,rev,payment ,row_number() over (partition by id,month order by rev desc) as rno from table1
) where rno=1
group by id
This presupposes you don't have more than one value per rev. If that's not the case, then you probably want a row_number analytic instead of max.
with latest as (
select
id, month, payment, rev,
max (rev) over (partition by id, month) as max_rev
from table1
)
select sum (payment)
from latest
where rev = max_rev
Or there's this, if I've understood the requirement right:
with demo as (
select 'A'as id, 1 as month, 10 as payment, 0 as rev from dual
union all select 'A',2,20,0 from dual
union all select 'A',2,30,1 from dual
union all select 'A',3,40,0 from dual
union all select 'A',4,50,0 from dual
union all select 'A',4,60,1 from dual
union all select 'A',4,70,2 from dual
)
select sum(payment) keep (dense_rank last order by rev)
from demo;
You can check the breakdown by including the key columns:
with demo as (
select 'A'as id, 1 as month, 10 as payment, 0 as rev from dual
union all select 'A',2,20,0 from dual
union all select 'A',2,30,1 from dual
union all select 'A',3,40,0 from dual
union all select 'A',4,50,0 from dual
union all select 'A',4,60,1 from dual
union all select 'A',4,70,2 from dual
)
select id, month, max(rev)
, sum(payment) keep (dense_rank last order by rev)
from demo
group by id, month;
select sum(payment) from tableName where id='A' and month=2 OR month=4 order by payment asc;

Unexpected result of multiset mapping in Oracle SQL

Please help me to confirm is that behavior explained below is a bug, or clearly explain why it's right.
There are a high probability that I misunderstood some concept, but now for me it looks like a bug.
All examples below simplified as much as possible to demonstrate core of the issue. Real situation is very complex, so only general answers and workarounds related to principle of query construction is acceptable.
You are welcome to ask clarifying questions in comments and i'll try to do my best to answer them.
Thank you for attention. :)
Question
Why in last Example (Example 5) collection instance in (select count(1) ... subquery from first row mapped to all rows of the table, while expected result is to map each collection instance to it's own row?
At the same time collections used in cardinality(...) expression chosen properly.
Same situation (not covered in examples) exists if constructed in this way collections used in from or where part of a query.
Test schema setup
(SQLFiddle)
create or replace type TabType0 as table of varchar2(100)
/
create table Table0( tab_str_field varchar2(100), tab_field TabType0)
nested table tab_field store as tab_field_table
/
insert into table0 (tab_str_field, tab_field) values (
'A',
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
) as TabType0)
)
/
insert into table0 (tab_str_field, tab_field) values (
'B',
cast(multiset(
select 'B' from dual union all
select 'C' from dual
) as TabType0)
)
/
insert into table0 (tab_str_field, tab_field) values (
'C',
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
) as TabType0)
)
/
insert into table0 (tab_str_field, tab_field) values (
'D',
cast(multiset(
select 'A' from dual
) as TabType0)
)
/
select 'Initial table data' caption from dual
/
select * from table0
/
table data:
| TAB_STR_FIELD | TAB_FIELD |
-----------------------------
| A | A,B,C |
| B | B,C |
| C | A,B,C,D |
| D | A |
Examples
Example 1 (SQLFiddle) - work with nested table fields - OK
select 'Work with nested table - OK' caption from dual
/
select
tab_field tab_field,
-- cardinality
cardinality(tab_field) tab_cardinality,
-- select from table field of current row
(select count(1) from table(tab_field)) tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(tab_field)
where column_value = tab_str_field
) same_value
from table0
/
results:
| TAB_FIELD | TAB_CARDINALITY | TAB_COUNT | SAME_VALUE |
--------------------------------------------------------
| A,B,C | 3 | 3 | A |
| B,C | 2 | 2 | B |
| A,B,C,D | 4 | 4 | C |
| A | 1 | 1 | (null) |
Example 2 (SQLFiddle) - work with constructed source data alone - OK
select 'Work with constructed source data alone - OK' caption from dual
/
with table_data_from_set as (
select
'A' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'B' tab_str_field,
cast(multiset(
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'C' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
) as TabType0) tab_field
from dual union all
select
'D' tab_str_field,
cast(multiset(
select 'A' from dual
) as TabType0) tab_field
from dual
)
select
tab_field tab_field,
-- cardinality
cardinality(tab_field) tab_cardinality,
-- select from table field of current row
(select count(1) from table(tab_field)) tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(tab_field)
where column_value = tab_str_field
) same_value
from table_data_from_set
/
results:
| TAB_FIELD | TAB_CARDINALITY | TAB_COUNT | SAME_VALUE |
--------------------------------------------------------
| A,B,C | 3 | 3 | A |
| B,C | 2 | 2 | B |
| A,B,C,D | 4 | 4 | C |
| A | 1 | 1 | (null) |
Example 3 (SQLFiddle) - join table with multisets constructed in WITH - OK
select 'Join table with multisets constructed in WITH - OK' caption from dual
/
with table_data_from_set as (
select
'A' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'B' tab_str_field,
cast(multiset(
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'C' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
) as TabType0) tab_field
from dual union all
select
'D' tab_str_field,
cast(multiset(
select 'A' from dual
) as TabType0) tab_field
from dual
)
select
table0.tab_field table0_tab_field,
table_data_from_set.tab_field set_tab_field,
-- cardinality
cardinality(table0.tab_field) table0_tab_cardinality,
cardinality(table_data_from_set.tab_field) set_tab_cardinality,
-- select from table field of current row
(select count(1) from table(table_data_from_set.tab_field)) set_tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(table_data_from_set.tab_field)
where column_value = table0.tab_str_field
) same_value
from
table0,
table_data_from_set
where
table_data_from_set.tab_str_field = table0.tab_str_field
/
results:
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE |
----------------------------------------------------------------------------------------------------------------
| A,B,C | A,B,C | 3 | 3 | 3 | A |
| B,C | B,C | 2 | 2 | 2 | B |
| A,B,C,D | A,B,C,D | 4 | 4 | 4 | C |
| A | A | 1 | 1 | 1 | (null) |
Example 4 (SQLFiddle) - join table with multisets constructed in WITH + subquery - OK
select 'Join table with multisets constructed in WITH and subquery - OK' caption from dual
/
with table_data_from_set as (
select
'A' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'B' tab_str_field,
cast(multiset(
select 'B' from dual union all
select 'C' from dual
) as TabType0) tab_field
from dual union all
select
'C' tab_str_field,
cast(multiset(
select 'A' from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual
) as TabType0) tab_field
from dual union all
select
'D' tab_str_field,
cast(multiset(
select 'A' from dual
) as TabType0) tab_field
from dual
)
select
table0_tab_field table0_tab_field,
set_tab_field set_tab_field,
-- cardinality
cardinality(table0_tab_field) table0_tab_cardinality,
cardinality(set_tab_field) set_tab_cardinality,
-- select from table field of current row
(select count(1) from table(set_tab_field)) set_tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(set_tab_field)
where column_value = table0_tab_str_field
) same_value
from (
select
table0.tab_str_field table0_tab_str_field,
table0.tab_field table0_tab_field,
table_data_from_set.tab_str_field set_tab_str_field,
table_data_from_set.tab_field set_tab_field
from
table0,
table_data_from_set
where
table_data_from_set.tab_str_field = table0.tab_str_field
)
/
results:
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE |
----------------------------------------------------------------------------------------------------------------
| A,B,C | A,B,C | 3 | 3 | 3 | A |
| B,C | B,C | 2 | 2 | 2 | B |
| A,B,C,D | A,B,C,D | 4 | 4 | 4 | C |
| A | A | 1 | 1 | 1 | (null) |
Example 5 (SQLFiddle) - join table with multisets constructed on the fly - FAILED
select 'Join table with multisets constructed on the fly - FAIL (set_tab_count wrong)' caption from dual
/
with string_set as (
select 'A' str_field from dual union all
select 'B' str_field from dual union all
select 'C' str_field from dual union all
select 'D' str_field from dual union all
select 'E' str_field from dual
)
select
table0_tab_field table0_tab_field,
set_tab_field set_tab_field,
-- cardinality
cardinality(table0_tab_field) table0_tab_cardinality,
cardinality(set_tab_field) set_tab_cardinality,
-- select from table field of current row
(select count(1) from table(set_tab_field)) set_tab_count,
-- select from field of current row while joining
-- with another field of same row
( select column_value from table(set_tab_field)
where column_value = table0_tab_str_field
) same_value
from (
select
table0.tab_str_field table0_tab_str_field,
table0.tab_field table0_tab_field,
(
cast(multiset(
select
string_set.str_field
from
string_set,
table(table0.tab_field) tab_table
where
string_set.str_field = tab_table.column_value
) as TabType0)
) set_tab_field
from
table0
)
/
result (all values in set_tab_count column are same - wrong! ) :
| TABLE0_TAB_FIELD | SET_TAB_FIELD | TABLE0_TAB_CARDINALITY | SET_TAB_CARDINALITY | SET_TAB_COUNT | SAME_VALUE |
----------------------------------------------------------------------------------------------------------------
| A,B,C | A,B,C | 3 | 3 | 3 | A |
| B,C | B,C | 2 | 2 | 3 | B |
| A,B,C,D | A,B,C,D | 4 | 4 | 3 | C |
| A | A | 1 | 1 | 3 | (null) |
Oracle version information
Instance 1
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
PL/SQL Release 11.2.0.3.0 - Production
CORE 11.2.0.3.0 Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production
Instance 2
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for 32-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
SQLFiddle with all queries together.
It's a bug. Adding a /*+ NO_MERGE */ hint to the second inline view in the last example will generate the expected results. See this SQL Fiddle for an example. Regardless of the query, that hint should never change the results. There are a couple of other seemingly unrelated changes you can make that will generate the correct results, such as removing some of the columns, or adding an unused ROWNUM in the middle.
Oracle is re-writing your query to optimize it, but doing something wrong. You could probably get some more information by tracing the query, but I doubt you'll be able to truly fix the issue. Work around it for now and submit a service request to Oracle so they can create a bug and eventually fix it.