-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy path33_xmlagg.sql
174 lines (163 loc) · 3.78 KB
/
33_xmlagg.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
create table characters (
id integer not null primary key,
name varchar2(100) unique,
faction varchar2(100)
);
create table favorite_food (
character_id integer not null references characters( id ),
food varchar2(4000)
);
insert into characters values (1, 'Chewbacca', 'Rebels');
insert into characters values (2, 'Darth Vader', 'Empire');
insert into characters values (3, 'Jar Jar Binks', 'Rebels');
insert into favorite_food values ( 1, 'Grilled Pork');
insert into favorite_food values ( 1, 'Cooked Pork');
insert into favorite_food values ( 1, 'Raw Pork');
insert into favorite_food values ( 2, 'Cheesecake');
commit;
select *
from characters c
inner join favorite_food ff on c.id = ff.character_id;
--This will cause an ORA-00935
select
xmlserialize(
document
xmlelement(
"Factions",
xmlagg(
xmlelement(
"Faction",
xmlattributes(c.faction as "name"),
xmlelement("Characters",
xmlagg(
xmlelement("Character",
xmlforest(
c.name as "name"
),
xmlelement("favouriteFoods",
xmlagg(
xmlforest(
ff.food as "food"
)
)
)
)
)
)
)
)
)
as clob indent size = 2
)
from characters c
left outer join favorite_food ff on c.id = ff.character_id
group by faction
;
-- As soon as we hit more than 2 levels of nesting, we need to use subqueries instead
select
xmlserialize(
document
xmlelement(
"Factions",
xmlagg(
xmlelement(
"Faction",
xmlattributes(c.faction as "name"),
xmlelement("Characters",
xmlagg(
xmlelement("Character",
xmlforest(
c.name as "name"
),
xmlelement("favouriteFoods",
(
select
xmlagg(
xmlforest(
ff.food as "food"
)
)
from favorite_food ff
where c.id = ff.character_id
)
)
)
)
)
)
)
)
as clob indent size = 2
)
from characters c
group by faction
;
-- We can even use a nice WITH clause to make it more readable
with character_foods as (
select
character_id,
xmlagg(
xmlforest(
food as "food"
)
) xml
from favorite_food
group by character_id
)
select
xmlserialize(
document
xmlelement(
"Factions",
xmlagg(
xmlelement(
"Faction",
xmlattributes(c.faction as "name"),
xmlelement("Characters",
xmlagg(
xmlelement("Character",
xmlforest(
c.name as "name"
),
xmlelement("favouriteFoods",
(
select xml
from character_foods cf
where cf.character_id = c.id
)
)
)
)
)
)
)
)
as clob indent size = 2
)
from characters c
group by faction
-- As JSON
select
json_serialize(
json_arrayagg(
json_object(
faction,
'characters' value json_arrayagg(
json_object(
name,
'favoriteFoods' value (
select
json_arrayagg(
ff.food
)
from favorite_food ff
where c.id = ff.character_id
)
)
)
)
)
pretty
)
from characters c
group by faction;