Skip to Main Content

Database Software

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

XMLTable(), aggregation (eg. sum) and GROUP BY

590223Sep 18 2007 — edited Sep 22 2007
Hi,

For performance reasons I'm using the XMLTable functionality on a OR table. Every root element of the XML document has an attribute with an unique ID. Now I want to do a sum or max of some recurring element in the XML document and return the aggregated value on a document basis, together with the document ID.

First the definition:
set long 10000000
set pages 5000
var schemaPath varchar2(256)
var schemaURL  varchar2(256)
var xmlSchema  clob;
--
begin
   :schemaURL := 'http://localhost/public/xsd/simple.xsd';
   :schemaPath := '/public/simple.xsd';
   :xmlSchema :=
'<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema
   xmlns="http://localhost/public/xsd/simple.xsd"
   targetNamespace="http://localhost/public/xsd/simple.xsd"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   xmlns:xdb="http://xmlns.oracle.com/xdb"
   elementFormDefault="qualified"
   attributeFormDefault="unqualified"
   xdb:storeVarrayAsTable="true">
  <xs:element name="root" xdb:defaultTable="simple_or" xdb:maintainDOM="false">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ea">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="eb" minOccurs="1" maxOccurs="unbounded">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="c1" type="xs:double" />
                    <xs:element name="c2" type="xs:double" />
                    <xs:element name="c3" type="xs:double" />
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
           </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute name="id" type="xs:string" use="required" /> 
    </xs:complexType>
  </xs:element>
</xs:schema>';
end;
/ 

alter session set events='31098 trace name context forever'
/ 

DECLARE
  BINARY_XML boolean:=FALSE;
BEGIN
   IF (BINARY_XML)
   THEN
      dbms_xmlschema.registerSchema(SCHEMAURL => :schemaURL,
                                    SCHEMADOC => :xmlschema,
                                    LOCAL     => TRUE,
                                    GENTYPES  => FALSE,
                                    GENBEAN   => FALSE,
                                    GENTABLES => FALSE,
                                    ENABLEHIERARCHY => DBMS_XMLSCHEMA.ENABLE_HIERARCHY_NONE,
                                    FORCE     => FALSE,
                                    OPTIONS   => DBMS_XMLSCHEMA.REGISTER_BINARYXML,
                                    OWNER     => USER);
   ELSE
      dbms_xmlschema.registerSchema(SCHEMAURL => :schemaURL,
                                    SCHEMADOC => :xmlSchema,
                                    LOCAL     => TRUE,
                                    GENTYPES  => TRUE,
                                    GENBEAN   => FALSE,
                                    GENTABLES => TRUE,
                                    ENABLEHIERARCHY => DBMS_XMLSCHEMA.ENABLE_HIERARCHY_NONE,
                                    FORCE     => FALSE,
                                    OWNER     => USER);
   END IF;
END;
/ 
And the data. I've loaded 10 documents each having 50.000 eb elements:
<?xml version="1.0" encoding="UTF-8"?>
<root id="1" xmlns="http://localhost/public/xsd/simple.xsd">
<ea>
<eb>
<c1>4.0</c1>
<c2>5.0</c2>
<c3>6.0</c3>
</eb>
<eb>
<c1>7.0</c1>
<c2>8.0</c2>
<c3>9.0</c3>
</eb>
<eb>
<c1>7.0</c1>
<c2>8.0</c2>
<c3>9.0</c3>
</eb>
<eb>
<c1>7.0</c1>
<c2>8.0</c2>
<c3>9.0</c3>
</eb>
...etc...
Getting the global max of c2 is quite easy (thanks to Marco and Mark):
SELECT max(c2)
  FROM "simple_or",
       xmltable
       (
         xmlnamespaces
         (
            default 'http://localhost/public/xsd/simple.xsd'
         ),
         '/root/ea/eb'
         passing OBJECT_VALUE
         columns
         C2 PATH 'c2'
       )
/ 
However, in most cases I need to have the maximum per document. So, in I need to introduce a group by functionality. Amongst other solutions, I've tried the following:
select id, max(c2)
  from "simple_or",
       xmltable
       (
         xmlnamespaces
         (
            default 'http://localhost/public/xsd/simple.xsd'
         ),
         '/root/ea/eb'
         passing OBJECT_VALUE
         columns
         C2 PATH 'c2',
         ID PATH './../../@id'
       )
GROUP BY id
/ 
This however only gives me one result, which is actually the global maximum again. The reason is that the './../../@id' doesn't return the proper value, but an empty something.

Anybody who knows how to rewrite the query above to something that works (while keeping in mind the performance)?
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Oct 20 2007
Added on Sep 18 2007
3 comments
1,662 views