如何聚合行并转换为列?
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
如果您使用的是 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。
有一个已解析的 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
如果您使用的是 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。