Parece ser un error. El plan de ejecución no sugiere ningún DISTINCT
operación que se está aplicando:
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
| 1 | SORT GROUP BY | | 1 | 26 | | |
|* 2 | TABLE ACCESS FULL| T2 | 1 | 26 | 3 (0)| 00:00:01 |
| 3 | SORT GROUP BY | | 1 | 13 | | |
| 4 | TABLE ACCESS FULL| T1 | 2 | 26 | 3 (0)| 00:00:01 |
---------------------------------------------------------------------------
Solución 1
Use un HAVING COUNT(*) = COUNT(*)
predicado:
select json_arrayagg(json_object(
key 't1_id' value t1_id,
key 't2' value (
select json_arrayagg(json_object(
key 't2_value' value t2_value
))
from (
select distinct t2.t2_value
from t2
where t2.t1_id = t1.t1_id
) t
having count(*) = count(*) -- Workaround
) format json
))
from t1;
Esto produce el resultado correcto:
[{
"t1_id":1,
"t2":[{ "t2_value":1 }]
}, {
"t1_id":2,
"t2":[{ "t2_value":2 }, { "t2_value":3 }]
}]
El plan ahora es:
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 7 (100)| |
|* 1 | FILTER | | | | | |
| 2 | SORT GROUP BY | | 1 | 13 | | |
| 3 | VIEW | | 1 | 13 | 4 (25)| 00:00:01 |
| 4 | SORT UNIQUE | | 1 | 26 | 4 (25)| 00:00:01 | <--
|* 5 | TABLE ACCESS FULL| T2 | 1 | 26 | 3 (0)| 00:00:01 |
| 6 | SORT GROUP BY | | 1 | 13 | | |
| 7 | TABLE ACCESS FULL | T1 | 2 | 26 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Solución alternativa 2
Usa una UNION
para hacer cumplir la distinción:
select json_arrayagg(json_object(
key 't1_id' value t1_id,
key 't2' value (
select json_arrayagg(json_object(
key 't2_value' value t2_value
))
from (
select distinct t2.t2_value
from t2
where t2.t1_id = t1.t1_id
union select null from dual where 1 = 0 -- Dummy union
) t
) format json
))
from t1;
El plan ahora es:
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 6 (100)| |
| 1 | SORT GROUP BY | | 1 | 13 | | |
| 2 | VIEW | | 2 | 26 | 3 (0)| 00:00:01 |
| 3 | SORT UNIQUE | | 2 | 26 | 3 (0)| 00:00:01 | <--
| 4 | UNION-ALL | | | | | |
|* 5 | TABLE ACCESS FULL| T2 | 1 | 26 | 3 (0)| 00:00:01 |
|* 6 | FILTER | | | | | |
| 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
| 8 | SORT GROUP BY | | 1 | 13 | | |
| 9 | TABLE ACCESS FULL | T1 | 2 | 26 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Y el resultado también es correcto