Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: Custom Function Help Needed?

Re: Custom Function Help Needed?

From: Thomas J. Kyte <tkyte_at_us.oracle.com>
Date: 2000/06/07
Message-ID: <8hml7s$p7p$1@nnrp1.deja.com>

In article <13e4506b.0695a1ed_at_usw-ex0107-055.remarq.com>,   gdas <gdas1NOgdSPAM_at_yahoo.com.invalid> wrote:
> I am trying to create a function that will essentially "SUM" a
> string. Unfortunately the built in SUM function works only on
> numeric datatypes. I can't simply concat || values because the
> values I'm trying to aggregate aren't within a single row, but
> rather span multiple rows in a column.
>
> As an example, imagine a query that is:
>
> select region, sum(sales_rep) from foo group by region
>
> I'd like this to return each region and the next cell should be
> a comma delimited list of all sales_reps in that particular
> region.
>
> Region sum(sales_rep)
> ------ --------------
> WEST Joe, Bill, Bob
> East Lisa, Steve, Mary
> etc...
> I created a custom function that basically fed in the "grouping"
> parameters (Region) and then that function loops through a
> cursor to return the appropriate value. no problems there.
>
> Only problem is that everything needs to be hardcoded in the
> function, particularly the input parameters. I'd like to
> simulate a dynamic group by here based on whatever other columns
> are in the select list for the query? Does anyone have a
> creative idea on this?
>
> One idea I had (if this is possible) was that if I could
> dynamically send as a parameter to my custom function the full
> text of the select statement...then inside of the function, I
> could parse that statement to determine the appropriate level of
> grouping. But in order to do this (again, it has to be dynamic
> because I can't hard code the statement as I would like to use
> this function in different scenarios), I need some kind of
> keyword or variable that will allow me to feed in the sql
> statement as a parameter to the function) Additionally, the
> application is end-user driven...so I have no idea what the
> users will be querying (it's a decision support app where people
> will be drilling up/down and all around) .
>
> If anyone has any creative ideas to this dilemma, I'd very much
> appreciate it if you could share your thoughts.
>
> Thanks in advance,
> Gavin
>
> * Sent from RemarQ http://www.remarq.com The Internet's Discussion
 Network *
> The fastest and easiest way to search and participate in Usenet -
 Free!
>
>

I will show 2 more ways to do it by calling PLSQL from sql. The first example uses static sql and hence you would need to code a routine per column/table you wished to "list" on. The second, more generic example, may be used on any table/column pair as it uses dynamic sql but only works in Oracle8i release 8.1 and up:

First we will set up a demo table. We have 2 columns A and B.  We desire output in the format:

A-value1            b-value1 b-value2 b-value3 ....
A-value2            b-value1 b-value2 ....


ask_tom_at_OSI1.WORLD> column t format a30
ask_tom_at_OSI1.WORLD> drop table t;
Table dropped.

ask_tom_at_OSI1.WORLD> create table t
  2 ( a varchar2(25),
  3 b varchar2(25)
  4 );

Table created.

ask_tom_at_OSI1.WORLD> insert into t values ( '210','5000' );
ask_tom_at_OSI1.WORLD> insert into t values ( '210','5001' );
ask_tom_at_OSI1.WORLD> insert into t values ( '210','5002' );
ask_tom_at_OSI1.WORLD> insert into t values ( '220','6001' );
ask_tom_at_OSI1.WORLD> insert into t values ( '220','6002' );
ask_tom_at_OSI1.WORLD> commit;

Commit complete.

Our first implementation simply uses static sql to select all of the values for B from T for a given A and string them together:

ask_tom_at_OSI1.WORLD> create or replace
  2 function get_transposed( p_a in varchar2 )   3 return varchar2
  4 is

  5      l_str  varchar2(2000) default null;
  6      l_sep  varchar2(1) default null;
  7  begin
  8      for x in ( select b from t where a = p_a ) loop
  9          l_str := l_str || l_sep || x.b;
 10          l_sep := '-';
 11      end loop;
 12      return l_str;

 13 end;
 14 /

Function created.

ask_tom_at_OSI1.WORLD>
ask_tom_at_OSI1.WORLD> select a, get_transposed( a ) t   2 from t
  3 group by a
  4 /

A                         T
------------------------- ------------------------------
210                       5000-5001-5002
220                       6001-6002


Our next example is more complex. We will pass in the name of the 'key' column (the column to pivot on), a value for that column, the name of the column to actually select out and string together and finally the table to select from:

ask_tom_at_OSI1.WORLD> create or replace

  2  function transpose( p_key_name in varchar2,
  3                      p_key_val  in varchar2,
  4                      p_other_col_name in varchar2,
  5                      p_tname     in varchar2 )
  6 return varchar2
  7 as
  8      type rc is ref cursor;
  9      l_str    varchar2(4000);
 10      l_sep    varchar2(1);
 11      l_val    varchar2(4000);
 12
 13      l_cur    rc;

 14 begin
 15
 16      open l_cur for 'select '||p_other_col_name||'
 17                        from '|| p_tname || '
 18                       where ' || p_key_name || ' = :x '
 19                  using p_key_val;
 20
 21      loop
 22          fetch l_cur into l_val;
 23          exit when l_cur%notfound;
 24          l_str := l_str || l_sep || l_val;
 25          l_sep := '-';
 26      end loop;
 27      close l_cur;
 28
 29      return l_str;

 30 end;
 31 /

Function created.

ask_tom_at_OSI1.WORLD>
ask_tom_at_OSI1.WORLD> REM List the values of "B" for a given value
ask_tom_at_OSI1.WORLD> REM of "A" in the table "T"
ask_tom_at_OSI1.WORLD>
ask_tom_at_OSI1.WORLD> select a, transpose( 'a', a, 'b', 't' ) t
  2 from t
  3 group by a
  4 /
A                         T
------------------------- ------------------------------
210                       5000-5001-5002
220                       6001-6002




--
Thomas Kyte (tkyte_at_us.oracle.com) Oracle Service Industries
Howtos and such: http://osi.oracle.com/~tkyte/index.html
Oracle Magazine: http://www.oracle.com/oramag
Opinions are mine and do not necessarily reflect those of Oracle Corp


Sent via Deja.com http://www.deja.com/
Before you buy.
Received on Wed Jun 07 2000 - 00:00:00 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US