[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: An XSLT equivalent of the SQL SUM and GROUP BY ope

Subject: Re: An XSLT equivalent of the SQL SUM and GROUP BY operations ?
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Mon, 21 May 2001 15:08:30 +0100
sql concat group by
Hi Andy,

This is a grouping problem, and as such I'd suggest that you use the
Muenchian Method for identifying the groups.

First, define a key that enables you to rapidly get all the lines with
a particular Account/Date combination.  You can specify the
Account/Date combination by concatenating the values of the two
elements together (with some appropriate separator).  For example:

<xsl:key name="lines"
         match="line"
         use="concat(Account, ':', Date)" />

With this key in place, you can get, for example, all the lines for
Account 64001 on 01/02/91 with:

  key('lines', '64001:01/02/91')

Once you have all these line elements, you can sum their Amount
children using the sum() function:

  sum(key('lines', '64001:01/02/91')/Amount)

So, that's well and good if you know the Account and Dates that you
want to access, but you don't know that in advance, so you need to
have some way of going through all the line elements to find those
that have unique Account/Date combinations and process them.

The unique line elements may as well be the first line elements with a
particular Account/Date combination; given a line element ($line), you
can check whether it's the same as the first one returned by the key
with that line's Account/Date combo by comparing their unique IDs
with:

  generate-id($line) =
  generate-id(key('lines', concat($line/Account, ':' $line/Date))[1])

or using set logic (if you union two sets that each contain the same
single node within them, then the union will only have one node in it;
if they're different it'll have two):

  count($line |
        key('lines', concat($line/Account, ':', $line/Date))[1]) = 1

So, what you need to do is go through all the line elements in turn
and check out whether they're the first returned by the key.  These
are the only ones you want to process, so apply templates to only
them:

  <xsl:apply-templates
     select="line[count(.|key('lines', concat(Account, ':', Date))[1])
                  = 1]" />

Then you want a template for the line elements that basically copies
it, but has the Amount element give the sum of the Amounts from all
the lines with that Amount/Date pair:

<xsl:template match="line">
   <line>
      <xsl:copy-of select="Account | Date" />
      <Amount>
         <xsl:value-of
            select="sum(key('lines',
                            concat(Account, ':', Date))/Amount)" />
      </Amount>
   </line>
</xsl:template>

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.