C:\cpanrun\depot\main\contrib-patched\perl\CPAN\src\Data-Grouper\blib/html/site/lib/Data/Grouper.html


SYNOPSI/pre <pre> <span class=``keyword''>my</span> <span class=``variable''>$grouper</span> <span class=``operator''>=</span> <span class=``variable''>new</span> <span class=``variable''>Data::Grouper</span><span class=``operator''>(</span> <span class=``string''>COLNAME/span <span class=``operator''>=&gt;</span> <span class=``operator''>[</span> <span class=``string''>'CATEGORY'</span><span class=``operator''>,</span><span class=``string''>'SUBCAT'</span><span class=``operator''>,</span><span class=``string''>'DESCR'</span><span class=``operator''>,</span><span class=``string''>'PRICE'</span><span class=``operator''>]</span><span class=``operator''>,</span> <span class=``string''>SORTCOL/span <span class=``operator''>=&gt;</span> <span class=``operator''>[</span> <span class=``string''>'CATEGORY'</span><span class=``operator''>,</span><span class=``string''>'SUBCAT'</span> <span class=``operator''>]</span> <span class=``operator''>);</span> </pre> <pre> <span class=``variable''>$sql</span> <span class=``operator''>=</span> <span class=``string''>'select category, subcat, description, price from order_items order by category, subcat'</span><span class=``operator''>;</span> <span class=``variable''>$aref</span> <span class=``operator''>=</span> <span class=``variable''>$dbh</span><span class=``operator''>-&gt;</span><span class=``variable''>selectall_arrayref</span><span class=``operator''>(</span><span class=``variable''>$sql</span><span class=``operator''>);</span> <span class=``variable''>$grouper</span><span class=``operator''>-&gt;</span><span class=``variable''>add_array</span><span class=``operator''>(</span><span class=``variable''>$aref</span><span class=``operator''>);</span> </pre> <pre> <span class=``variable''>$t</span> <span class=``operator''>=</span> <span class=``variable''>HTML::Template</span><span class=``operator''>-&gt;</span><span class=``variable''>new</span><span class=``operator''>(</span><span class=``string''>filename</span><span class=``operator''>=&gt;</span><span class=``string''>'../foobar.htmlt'</span><span class=``operator''>);</span> <span class=``variable''>$t</span><span class=``operator''>-&gt;</span><span class=``variable''>param</span><span class=``operator''>(</span><span class=``string''>OUTER</span><span class=``operator''>=&gt;</span><span class=``variable''>$grouper</span><span class=``operator''>-&gt;</span><span class=``variable''>get_data</span><span class=``operator''>());</span> <span class=``keyword''>print</span> <span class=``variable''>$t</span><span class=``operator''>-&gt;</span><span class=``variable''>output</span><span class=``operator''>;</span> </pre> <p>Lazy? Me too. The DATA param can use only two calls:</p> <pre> <span class=``variable''>$sql</span> <span class=``operator''>=</span> <span class=``string''>'select category, subcat, description, price from order_items order by style, color'</span><span class=``operator''>;</span> <span class=``variable''>$aref</span> <span class=``operator''>=</span> <span class=``variable''>$dbh</span><span class=``operator''>-&gt;</span><span class=``variable''>selectall_arrayref</span><span class=``operator''>(</span><span class=``variable''>$sql</span><span class=``operator''>,</span> <span class=``operator''>{</span><span class=``string''>Slice</span><span class=``operator''>=&gt;</span><span class=``operator''>{}}</span><span class=``operator''>);</span> </pre> <pre> <span class=``keyword''>my</span> <span class=``variable''>$g</span> <span class=``operator''>=</span> <span class=``variable''>new</span> <span class=``variable''>Data::Grouper</span><span class=``operator''>(</span><span class=``string''>DATA</span><span class=``operator''>=&gt;</span><span class=``variable''>$aref</span><span class=``operator''>,</span><span class=``string''>SORTCOL/span<span class=``operator''>=&gt;</span><span class=``operator''>[</span><span class=``string''>'CATEGORY'</span><span class=``operator''>,</span><span class=``string''>'SUBCAT'</span><span class=``operator''>]</span><span class=``operator''>);</span> </pre> <pre> <span class=``variable''>$t</span> <span class=``operator''>=</span> <span class=``variable''>HTML::Template</span><span class=``operator''>-&gt;</span><span class=``variable''>new</span><span class=``operator''>(</span><span class=``string''>filename</span><span class=``operator''>=&gt;</span><span class=``string''>'../foobar.htmlt'</span><span class=``operator''>);</span> <span class=``variable''>$t</span><span class=``operator''>-&gt;</span><span class=``variable''>param</span><span class=``operator''>(</span><span class=``string''>OUTER</span><span class=``operator''>=&gt;</span><span class=``variable''>$g</span><span class=``operator''>-&gt;</span><span class=``variable''>get_data</span><span class=``operator''>());</span> <span class=``keyword''>print</span> <span class=``variable''>$t</span><span class=``operator''>-&gt;</span><span class=``variable''>output</span><span class=``operator''>;</span>


   <span class="variable">And</span> <span class="variable">the</span> <span class="variable">fragment</span> <span class="variable">from</span> <span class="variable">the</span> <span class="variable">HTML::Template</span> <span class="variable">code</span><span class="operator">:</span>
</pre>
<pre>
   &lt;TMPL_LOOP NAME=OUTER&gt;
        &lt;h1&gt;Style: &lt;TMPL_VAR NAME=CATEGORY&gt;&lt;/h1&gt;
      &lt;TMPL_LOOP NAME=INNER&gt;
        &lt;h2&gt;Color: &lt;TMPL_VAR NAME=SUBCAT&gt; &lt;/h2&gt;
          &lt;table&gt;
          &lt;TMPL_LOOP NAME=INNER&gt;          
            &lt;tr&gt;&lt;td&gt; &lt;TMPL_VAR NAME=DESCR&gt;&lt;/td&gt;&lt;td&gt;&lt;TMPL_VAR NAME=PRICE&gt;&lt;/td&gt;&lt;/tr&gt;
          &lt;/TMPL_LOOP&gt;
          &lt;/table&gt;
      &lt;/TMPL_LOOP&gt;
      &lt;tr&gt;&lt;td&gt;&amp;nbsp&lt;/td&gt;&lt;td&gt;&lt;TMPL_VAR NAME=SUM_PRICE&gt;&lt;/td&gt;&lt;/tr&gt;
   &lt;/TMPL_LOOP&gt;</pre>
<p>This might produce output like:</p>
<pre>
  Toys
    Nerf Toys
      Nerf Dart Gun                  20.00
      Nerf Footbal                   30.00</pre>
<pre>
                                     50.00
  Video Games
    X Box
      Gothic Something or Other      10.00
    Playstation 2
      Gran Turismo 3 A-Spec          15.00
      Grand Theft Auto 3             10.00

                                     35.00

This is not my most inspired example ever.  Except for the PS2 bits.</pre>
<p>
</p>
<hr />
<h1><a name="description">DESCRIPTION</a></h1>
<p>This is a helper object for the various templating modules
that exist.  A key feature of any templating system is
the ability to deal with loops of data, for example
rows in a table.  Most systems will deal with nested
looping.  Data::Grouper takes the work out of
prepaing the data structures for nested loops.</p>
<p>Grouper will help you the most if you are writing reports
that have multiple layers of grouping with aggregate  values
but also need to display the detail rows.  An SQL select statement will 
get you one or the other of these features, but not both at
the same time.  And you still have to construct your data
structure for HTML::Template.  Grouper does it all.</p>
<p>
</p>
<hr />
<h1><a name="methods">METHODS</a></h1>
<p>
</p>
<h2><a name="new__"><code>new()</code></a></h2>
<p>Most of the behavior of grouper is determined by the parameters
passed to the constructor.</p>
<ul>
<li>
<p>COLNAMES - define column names for use with TMPL_VAR</p>
<p>Tell grouper the column names.
These are used when creating the hashes for HTML:Template.  COLNAMES
should contain the names of the hash values in the order the values
will appear in the rows passed to <code>add_row()</code>.
So for the following code:</p>
<pre>
   COLNAMES =&gt; [ 'RESP_DESC','DUTY_ID', 'DUTY_DESC']</pre>
<p>The hashes in the output structure will have keys RESP_DESC, 
DUTY_ID, and DUTY_DESC.  This allows them to be used in 
&lt;TMPL_VAR&gt; directives.</p>
<p>If you are using add_hash or add_array with an array of hash
references, you may omit COLNAMES.  If COLNAMES is omitted,
the keys of the first incoming hash will become the contents
of COLNAMES.  Keep in mind that these are case sensitive.</p>
</li>
<li>
<p>AGGREGATES - Columns for which totals should be computed</p>
<p>This parameter gets a reference to an array of column names
to compute aggregate functions on.  Aggregate functions are
the same as you would find in SQL: sum, avg, min, max.</p>
<p>At every level of grouping, aggregate values will be provided.</p>
<p>Aggregate values are automatically given names based on the 
aggregate function and the column name.  Specifically, one of 
SUM_, MIN_, MAX_, or AVG_ is prepended to the column name.</p>
<p>Top level aggregates are contained in a hash obtainable with the
<code>get_top_aggregates()</code> function.</p>
</li>
<li>
<p>SORTCOLS - Columns to group on</p>
<p>This parameter is a reference to an array of column names to
sort on.  The number of &lt;TMPL_LOOPS&gt; in your template
will be equal to the number of column names you indicate here.</p>
<p>The rows passed to grouper MUST BE SORTED on the columns
indicated in SORT_COLS.</p>
</li>
<li>
<p>DATA - Array ref of hash or array refs</p>
<p>If you are using selectall_arrayref and not modifying the data before
sending it to grouper, you can reduce your grouper code to two calls
by using the DATA parameter in the grouper-&gt;<code>new()</code> constructor:</p>
<pre>
   <span class="keyword">my</span> <span class="variable">$g</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">Data::Grouper</span><span class="operator">(</span><span class="string">DATA</span><span class="operator">=&gt;</span><span class="variable">$aref</span><span class="operator">,</span><span class="string">SORTCOLS</span><span class="operator">=&gt;</span><span class="operator">[</span><span class="string">'STYLE'</span><span class="operator">,</span><span class="string">'COLOR'</span><span class="operator">]</span><span class="operator">);</span>
   <span class="variable">$g</span><span class="operator">-&gt;</span><span class="variable">get_data</span><span class="operator">();</span>

   <span class="variable">This</span> <span class="variable">will</span> <span class="variable">often</span> <span class="variable">be</span> <span class="variable">your</span> <span class="variable">best</span> <span class="variable">approach</span><span class="operator">.</span>
</pre>
</li>
<li>
<p>FORMAT - Formatting Functions</p>
<pre>
 <span class="keyword">my</span> <span class="variable">$cr</span> <span class="operator">=</span> <span class="keyword">sub</span><span class="variable"> </span><span class="operator">{</span> <span class="keyword">sprintf</span> <span class="string">"\$%.2f"</span><span class="operator">,</span> <span class="keyword">shift</span><span class="operator">;</span> <span class="operator">};</span>
 <span class="keyword">my</span> <span class="variable">$g</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">Data::Grouper</span><span class="operator">(</span> 
                  <span class="string">FORMAT</span><span class="operator">=&gt;</span> <span class="operator">{</span> <span class="string">'Count'</span><span class="operator">=&gt;</span><span class="variable">$cr</span><span class="operator">,</span> <span class="string">'SUM_Count'</span><span class="operator">=&gt;</span><span class="variable">$cr</span> <span class="operator">}</span>
                  <span class="operator">);</span>
</pre>
<p>This parameter is a reference to a hash from column names (as
specified in COLNAMES) to formatting functions.  A formatting
function takes one parameter and returns the formatted value
of that parameter.  Such a function might be used, for 
example, to format money values.</p>
</li>
</ul>
<p>
</p>
<h2><a name="add_array">add_array</a></h2>
<p>The add_array function adds multiple rows into the grouper
in one function call.  It takes one parameter, an array
reference.  This array can contain either hash references
or array references.</p>
<p>Add_array is especially useful with DBI.  DBI can return 
entire arrays with selectall_arrayref.  This
function lets you just pass an array ref in instead of doing
a while loop and calling add_row (or add_hash) for each row.</p>
<pre>
   <span class="variable">$aref</span> <span class="operator">=</span> <span class="variable">$dbh</span><span class="operator">-&gt;</span><span class="variable">selectall_arrayref</span><span class="operator">(</span><span class="variable">$sql</span><span class="operator">);</span>
   <span class="variable">$grouper</span><span class="operator">-&gt;</span><span class="variable">add_array</span><span class="operator">(</span><span class="variable">$aref</span><span class="operator">);</span>
</pre>
<p>Just like add_row, add_array expects that the data is sorted
on the columns that are specified in SORTCOLS.</p>
<p>
</p>
<h2><a name="add_row">add_row</a></h2>
<p>This takes a list of scalar values, which should correspond to the
entries in COLNAMES, and puts it in the correct 
place in the data structure.  Data in the successive calls to 
add_row is expected to be sorted on the columns specified in
SORTCOLS.</p>
<p>One reason to use add_row over add_array is if some transformation
happens between retrieving the data and populating the data
structure.</p>
<p>
</p>
<h2><a name="add_hash">add_hash</a></h2>
<p>This function is the hash-equivalent to add_row (above).  Add_hash
takes one parameter, a hash reference, which contains one 
row of data.  For example:</p>
<pre>
  <span class="variable">$href</span> <span class="operator">=</span> <span class="operator">{</span> <span class="string">COLOR</span><span class="operator">=&gt;</span><span class="string">'Red'</span><span class="operator">,</span> <span class="string">Size</span><span class="operator">=&gt;</span><span class="string">'13'</span><span class="operator">,</span> <span class="string">Style</span><span class="operator">=&gt;</span><span class="string">'Running'</span> <span class="operator">}</span><span class="operator">;</span>
  <span class="variable">add_hash</span> <span class="operator">(</span><span class="variable">$href</span><span class="operator">);</span>
</pre>
<p>This would add one row of data to the grouper.  To add multiple
rows, for example if you had an array of hash refs from DBI,
you would use <code>add_array()</code>.</p>
<p>The hash is assumed to contain the keys from COLNAMES.  If COLNAMES was not 
specified, the keys from the first hash passed to this function are used.  
Grouper makes its own copy of the hash ref to avoid modifying any data
that is passed in.</p>
<p>
</p>
<h2><a name="add_details">add_details</a></h2>
<p>Sometimes you will want to add some additional information
to a row or a parent.  This function helps you do that.</p>
<p>I'm not certain this function is useful and will stay.</p>
<p>
</p>
<h2><a name="get_data">get_data</a></h2>
<p>This function returns the array refernces required for
the call to HTML::Template's <code>param()</code> function.</p>
<p>
</p>
<h2><a name="get_top_aggregates">get_top_aggregates</a></h2>
<p>This function returns a reference to a hash containing top level aggregates
for the data.  Top level aggregates are contained in their own separate
hash since aggregates are normally one level up in the data structure from
the array containing their rows, but in the case of the top level, it is
impossible to go up one level.</p>
<p>Some top level aggregates may be best computed outside of Data::Grouper.
For example, while Grouper could maintain a count of total rows, if 
you were using add_array this statistic is just the size of the array,
which is computed much more efficiently as $#array.</p>
<p>Right now G::D computes top level aggregates if any aggregates are being
computed.  In the future there may be an option to disable computation
of top level aggregates.  Actually, they should probably be disabled by
default.</p>
<p>
</p>
<hr />
<h1><a name="more_examples">More Examples</a></h1>
<p>Suppose you have a table of book data with columns genre, title.  You might
have this data:</p>
<pre>
 Non-Fiction, Techincal, Effective Perl, 25
 Non-Fiction, Technical, The C Programming Language, 20
 Non-Fiction, Techincal, Lex &amp; Yacc, 20
 Non-Fiction, Philosophy, Book of Five Rings, 13
 Non-Fiction, Philosophy, Against Method, 30
 Fiction, Sci-Fi, Lord of the Rings,25
 Fiction, Sci-Fi, Foundation,15
 Fiction, Literary, Gravity's Rainbow,15

Say you want to display these, grouped by genre.  You need to build</pre>
<pre>
 <span class="variable">@data</span> <span class="operator">=</span> <span class="operator">[</span>
   <span class="operator">{</span> <span class="string">FICTION</span><span class="operator">=&gt;</span> <span class="variable">Non</span><span class="operator">-</span><span class="variable">Fiction</span><span class="operator">,</span>
     <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span>
       <span class="operator">{</span> <span class="string">GENRE</span> <span class="operator">=&gt;</span> <span class="variable">Technical</span><span class="operator">,</span>
         <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span>  <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Effective</span> <span class="variable">Perl</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">25</span><span class="operator">}</span><span class="operator">,</span>
                     <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">The</span> <span class="variable">C</span> <span class="variable">Programming</span> <span class="variable">Language</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">20</span> <span class="operator">}</span><span class="operator">,</span>
                     <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Lex</span><span class="operator">&amp;</span><span class="variable">Yacc</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">20</span> <span class="operator">}</span>
                  <span class="operator">]</span>
       <span class="operator">}</span><span class="operator">,</span>
       <span class="operator">{</span> <span class="string">GENRE</span> <span class="operator">=&gt;</span> <span class="variable">Philosophy</span><span class="operator">,</span>
         <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span> <span class="operator">{</span><span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Book</span> <span class="variable">of</span> <span class="variable">Five</span> <span class="variable">Rings</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">13</span> <span class="operator">}</span><span class="operator">,</span>
                    <span class="operator">{</span><span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Against</span> <span class="variable">Method</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">30</span> <span class="operator">}</span>
                  <span class="operator">]</span>
       <span class="operator">}</span>
     <span class="operator">]</span>
   <span class="operator">}</span><span class="operator">,</span>
   <span class="operator">{</span> <span class="string">FICTION</span><span class="operator">=&gt;</span> <span class="variable">Fiction</span><span class="operator">,</span>
     <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span>  
       <span class="operator">{</span> <span class="string">GENRE</span><span class="operator">=&gt;</span> <span class="variable">Sci</span><span class="operator">-</span><span class="variable">Fi</span><span class="operator">,</span>
         <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span> <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Lord</span> <span class="variable">of</span> <span class="variable">the</span> <span class="variable">Rings</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">25</span> <span class="operator">}</span><span class="operator">,</span>
                    <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Foundation</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">15</span> <span class="operator">}</span>
                  <span class="operator">]</span>
       <span class="operator">}</span><span class="operator">,</span>
       <span class="operator">{</span> <span class="string">GENRE</span><span class="operator">=&gt;</span> <span class="variable">Literary</span><span class="operator">,</span>
         <span class="string">INNER</span> <span class="operator">=&gt;</span> <span class="operator">[</span> <span class="operator">{</span> <span class="string">TITLE</span><span class="operator">=&gt;</span><span class="variable">Gravity's</span> <span class="variable">Rainbow</span><span class="operator">,</span> <span class="string">PRICE</span><span class="operator">=&gt;</span><span class="number">15</span> <span class="operator">}</span> <span class="operator">]</span>
       <span class="operator">}</span>     
   <span class="operator">}</span>
 <span class="operator">]</span><span class="operator">;</span>
</pre>
<p>and apply it to template</p>
<pre>
 &lt;TMPL_LOOP NAME=OUTER&gt;
 &lt;h2&gt;&lt;TMPL_VAR NAME=GENRE&gt;&lt;/h2&gt;
   &lt;TMPL_LOOP NAME=INNER&gt;
     &lt;TMPL_VAR NAME=TITLE&gt; &lt;br&gt;
   &lt;/TMPL_LOOP&gt;
   Average Price: &lt;TMPL_VAR NAME=AVG_PRICE&gt;
 &lt;/TMPL_LOOP&gt;</pre>
<p>to get</p>
<pre>
 Non-Fiction
   Technical
     Effective Perl
     The C Programming Language
     Lex &amp; Yacc
     Average Price: 21.6
   Philosophy
    Book of Five Rings
    Against Method
    Average Price: 21.5
 Fiction
   Sci-Fi
     Lord of the Rings
     Foundation
   Literary
     Gravity's Rainbow

If you are getting your data from a database, you might do this:</pre>
<pre>
 <span class="variable">$sql</span> <span class="operator">=</span> <span class="string">'select fiction, genre, title from books order by fiction, genre'</span><span class="operator">;</span>
 <span class="variable">$aref</span> <span class="operator">=</span> <span class="variable">$dbh</span><span class="operator">-&gt;</span><span class="variable">selectall_arrayref</span><span class="operator">(</span><span class="variable">$sql</span><span class="operator">);</span>
 <span class="variable">$grouper</span><span class="operator">-&gt;</span><span class="variable">add_array</span><span class="operator">(</span><span class="variable">$aref</span><span class="operator">);</span>
</pre>
<p>Grouper creates the array of hash refs, containing array refs with hash
refs that H::T requires.</p>
<p>
</p>
<hr />
<h1><a name="faqs">FAQs</a></h1>
<p>
</p>
<h2><a name="how_is_this_different_than_group_by_in_sql">How is this different than GROUP BY in SQL?</a></h2>
<p>SQL's group by facility allows grouping at only one level and
does not provide the underlying detail data.  Grouper is used
to provide summary details at multiple levels while still providing
the underlying data, all in a format you can use with HTML::Template.</p>
<p>
</p>
<hr />
<h1><a name="author">AUTHOR</a></h1>
<p>David Ferrance (<a href="mailto:dave@ferrance.com";>dave@ferrance.com</a>)</p>
<p>
</p>
<hr />
<h1><a name="license">LICENSE</a></h1>
<p>Data::Grouper - A module for using aggregating data for use with various Template modules.</p>
<p>Copyright (C) 2001,2002 David Ferrance (<a href="mailto:dave@ferrance.com";>dave@ferrance.com</a>)  All Rights Reserved.</p>
<p>This module is free software. It may be used, redistributed and/or modified under the same terms as perl itself.</p>

</body>

</html>

 C:\cpanrun\depot\main\contrib-patched\perl\CPAN\src\Data-Grouper\blib/html/site/lib/Data/Grouper.html