Search code examples
xmlxquerymarklogic

Group By and Count in Xquery


I am trying to count Similar 'itemid_ref', to get numbers of each Items ref in this:

<?xml version="1.0" encoding="utf-8"?>
<electrystore>
  <itembill>
   <itembill_id>1</itembill_id>
   <itemid_ref>2</itemid_ref>
   <billid_ref>2</billid_ref>
   <price>20000</price> 
  </itembill>
   <itembill>
   <itembill_id>2</itembill_id>
   <itemid_ref>3</itemid_ref>
   <billid_ref>3</billid_ref>
   <price>250000</price> 
  </itembill>
  <itembill>
   <itembill_id>3</itembill_id>
   <itemid_ref>3</itemid_ref>
   <billid_ref>3</billid_ref>
   <price>30000</price> 
  </itembill>
  <itembill>
   <itembill_id>4</itembill_id>
   <itemid_ref>1</itemid_ref>
   <billid_ref>2</billid_ref>
   <price>140000</price> 
  </itembill>
  <itembill>
   <itembill_id>5</itembill_id>
   <itemid_ref>2</itemid_ref>
   <billid_ref>1</billid_ref>
   <price>10000</price> 
  </itembill>
</electrystore>

I am trying to get the output from xquery to be like this:

<?xml version="1.0" encoding="UTF-8"?>
<results>
<result>
    <itemid_ref>
       2
    </itemid_ref>
    <numberOfitemes>2</numberOfitemes>
</result>
<result>
    <itemid_ref>
       3
    </itemid_ref>
    <numberOfitemes>2</numberOfitemes>
</result>
<result>
   <itemid_ref>
       1
    </itemid_ref>
    <numberOfitemes>1</numberOfitemes>
</result>

how can I do this?


Solution

  • There's no group by in XQuery 1.0, but usually you can get by using distinct-values, as long as the data set isn't too large.

    for $itemid_ref in distinct-values(/electrystore/itembill/itemid_ref)
    let $count := count(/electrystore/itembill[itemid_ref = $itemid_ref])
    return element result {
      element itemid_ref { $itemid_ref },
      element numberOfitemes { $count }
    }
    

    To be performant on large sets of data, you'll probably need to look into extensions available within your XQuery processor that allow access to indexes.

    In XQuery 3.0 it's a little simpler:

    for $itembill in /electrystore/itembill
    let $itemid_ref := $itembill/itemid_ref
    group by $itemid_ref
    return element result {
      element itemid_ref { $itemid_ref },
      element numberOfitemes { count($itembill) }
    }