如何聚合行并转换为列?

How to aggregate rows and converts into columns?

有一个已解析的 table table_1:

|id | parent_id | name    | value |
+---+-----------+---------+-------+  
| 1 | 0         | NumDoc  | 63    | 
| 2 | 0         | Groups  | null  |
| 4 | 3         | Group   | ALM   |
| 5 | 3         | Vals    | null  |
| 7 | 6         | ValCode | USD   |
|10 | 9         | ValCode | CHF   |
|11 | 3         | Group   | TLD   |
|12 | 3         | Vals    | null  |
|14 | 13        | ValCode | USD   |
|17 | 16        | ValCode | RUB   |  

我期待这样的结果:

| Numdoc | Group | Valcode |
+--------+------+----------+  
| 63     | ALM  | USD      |
| 63     | ALM  | CHF      |
| 63     | TLD  | USD      |
| 63     | TLD  | RUB      |    

我的sqlselect查询:

with t as( select * from(  
       select (case when c.name='NumDoc' then c.Value end) NumDoc,
              (case when c.name='Group' then c.Value end) as Group, 
              (case when c.name='ValCode' then c.Value end) as ValCode,
               rownum as rn
         from  table_1 c))
select NumDoc, 
       min(Group), 
       min(ValCode)
from(select t.*, row_number() over (partition by NumDoc, rn order by rn) as seqnum 
     from t) T
group by NumDoc,seqnum,Group, ValCode   

结果select:

| Numdoc | Group | Valcode |
+--------+-------+---------+  
| null   | null  | null    |
| null   | null  | CHF     |
| null   | null  | RUB     |
| null   | null  | USD     |
| null   | ALM   | null    |
| null   | TLD   | null    |
| 63     | null  | null    |

我不清楚 parent_id 与 id 有何关系。

但是如果我们建议 json 已经被解析为 table table_1 并且 ValCode 的 ID 总是在它的组和下一个组 ID 之间,那么:

select q1.value "Numdoc", 
       q2.value "Group", 
       q3.value "Valcode"  
 from (select id, value, lead(id) over (order by id) next_numdoc_id
         from table_1 
        where name='NumDoc') q1
 join (select id, value, lead(id) over (order by id) next_group_id
         from table_1 
        where name='Group') q2
   on q2.id between q1.id and nvl(q1.next_numdoc_id-1,q2.id)      
 join (select id, value
         from table_1 
        where name='ValCode') q3
   on q3.id between q2.id and nvl(q2.next_group_id-1,q3.id)     
 order by q1.value, q2.value, q3.value

https://dbfiddle.uk 聚合行 example

如果您使用的是 Oracle 12c 或更高版本,只需调用一次 json_table 即可轻松从原始 JSON(处于当前状态或已清理)获得预期结果,使用嵌套路径获取子元素:

select jt.*
from json_table ('<your JSON>', '$'
   columns
      numdoc number path '$.NumDoc',
      nested path '$.Groups[*]'
         columns (
           groupcode varchar2(3) path '$.GroupCode',
           nested path '$.Vals[*]'
              columns (
                 valcode varchar2(3) path '$.StValCode'
              )
         )
) jt
NUMDOC | GROUPCODE | VALCODE
-----: | :-------- | :------
    63 | ALM       | USD    
    63 | ALM       | CHF    
    63 | TLD       | USD    
    63 | TLD       | RUB    

db<>fiddle demo 从 CTE 提供 JSON。