Aggregate function on "large value type"

We are constrained to use a model that stores records in a main table and various attributes of the record in a second table. Something like this: main record table CAR, attribute table CAR_DETAILS with CAR_DETAILS have key value pairs like "color"
"blue" and "doors" "4".
For reports we need to flatten the one to many nature of this to get CAR and color and doors by using an aggregate function like: 
car_id, max(car_detail.value) filtered on car_detail.key = "color", max(car_detail.value) filtered on car_detail.key = "doors". 
This works on other tables but the car_detail table (shall we say) appears to store its values as blobs. In any case when we attempt to aggregate we get "The query uses an aggregate function on a large value type expression. Large value type expressions
can not be aggregated."
Since we can't change the model, we would need to use another function to change this to a smaller string (or date, these are actually mostly date), but none of the very limited set of functions available seems to work to make this aggregation possible (and
there is no "first" or anything else similar). 
The list of functions available in Report Model Queries can be found at https://msdn.microsoft.com/en-us/library/ee210538.aspx
Appreciate any ideas on how to solve this
 

I found a work around : create a second dataset reversing the direction:
car_detail.key, car_detail.value, car_id
with this filtered by car_detail.key = "color" (or doors etc)
Then use a lookup from the first dataset to the second to display the data:
=Lookup(Fields!car_Id.Value,Fields!Icar_Id.Value,Fields!car_detail.Value, "DataSet2")
where the 1st field is in the main report dataset, the second and third are in the lookup dataset, and the 4th parameter is the name of the lookup dataset. 
Would still really like to have a solution that allows aggregation for ease of use and efficiency. 

Similar Messages

  • How to use aggregate function with Date

    Hi All,
    I have a group of date from that is it possible to Max and Min of date.
    I have tried like this but its errored out <?MIN (current-group()/CREATION_DATE)?>.
    I have also tried like this but it doesnt works
    <?xdoxslt:minimum(CREATION_DATE)?>
    Is it possible to use aggregate function with date values.
    Thanks & Regards
    Srikkanth

    Hi KAVI PRIYA,
    if date is not in cannonical format, how can we change it in BI publisher, then how to calcualte minimum and as well as maximum.
    please advise me,
    Thanks,
    Sri

  • Trying to create a Histogram type/object for aggregate functions

    Hi,
    I am trying to create an aggregate function that will return a histogram
    type.
    It doesn't have to be an object that is returned, I don't mind returning
    a string but I would like to keep the associative array (or something
    else indexed by varchar2) as a static variable between iterations.
    I started out with the SecondMax example in
    http://www.csis.gvsu.edu/GeneralInfo/Oracle/appdev.920/a96595/dci11agg.htm#1004821
    But even seems that even a simpler aggregate function like one strCat
    below (which works) has problems because I get multiple permutations for
    every combination. The natural way to solve this would be to create an
    associative array as a static variable as part of the Histogram (see
    code below). However, apparently Oracle refuses to accept associate
    arrays in this context (PLS-00355 use of pl/sql table not allowed in
    this context).
    If there is no easy way to do the histogram quickly can we at least get
    something like strCat to work in a specific order with a "partition by
    ... order by clause"? It seems that even with "PARALLEL_ENABLE"
    commented out strCat still calls merge for function calls like:
    select hr,qtr, count(tzrwy) rwys,
    noam.strCat(cnt) rwycnt,
    noam.strCat(tzrwy) config,
    sum(cnt) cnt, min(minscore) minscore, max(maxscore) maxscore from
    ordrwys group by hr,qtr
    Not only does this create duplicate entries in the query result like
    "A,B,C" and "A,C,B" it seems that the order in rwycnt and config are not
    always the same so a user can not match the results based on their
    order.
    The difference between my functions and functions like sum and the
    secondMax demonstrated in the documentation is that secondMax does not
    care about the order in which it gets its arguments and does not need to
    maintain an ordered set in order to return the correct results. A good
    example of a built in oracle function that does care about all its
    arguments and probably has to maintain a similar data structure to the
    one I want is the PERCTILE_DISC function. If you can find the code for
    that function (or something like it) and forward a reference to me that
    in itself would be very helpful.
    Thanks,
    K.Dingle
    CREATE OR REPLACE type Histogram as object
    -- TYPE Hist10 IS TABLE OF pls_integer INDEX BY varchar2(10),
    -- retval hist10;
    -- retval number,
    retval noam.const.hist10,
    static function ODCIAggregateInitialize (sctx IN OUT Histogram)
    return number,
    member function ODCIAggregateIterate (self IN OUT Histogram,
    value IN varchar2) return number,
    member function ODCIAggregateTerminate (self IN Histogram,
    returnValue OUT varchar2,
    flags IN number) return number,
    member function ODCIAggregateMerge (self IN OUT Histogram,
    ctx2 IN Histogram) return number
    CREATE OR REPLACE type body Histogram is
    static function ODCIAggregateInitialize(sctx IN OUT Histogram) return
    number is
    begin
    sctx := const.Hist10();
    return ODCIConst.Success;
    end;
    member function ODCIAggregateIterate(self IN OUT Histogram, value IN
    varchar2)
    return number is
    begin
    if self.retval.exist(value)
    then self.retval(value):=self.retval(value)+1;
    else self.retval(value):=1;
    end if;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateTerminate(self IN Histogram,
    returnValue OUT varchar2,
    flags IN number)
    return number is
    begin
    returnValue := self.retval;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateMerge(self IN OUT Histogram,
    ctx2 IN Histogram) return number is
    begin
    i := ctx2.FIRST; -- get subscript of first element
    WHILE i IS NOT NULL LOOP
    if self.retval.exist(ctx2(i))
    then self.retval(i):=self.retval(i)+ctx2.retval(i);
    else self.retval(value):=ctx2.retval(i);
    end if;
    i := ctx2.NEXT(i); -- get subscript of next element
    END LOOP;
    return ODCIConst.Success;
    end;
    end;
    CREATE OR REPLACE type stringCat as object
    retval varchar2(16383), -- concat of all value to now varchar2, --
    highest value seen so far
    static function ODCIAggregateInitialize (sctx IN OUT stringCat)
    return number,
    member function ODCIAggregateIterate (self IN OUT stringCat,
    value IN varchar2) return number,
    member function ODCIAggregateTerminate (self IN stringCat,
    returnValue OUT varchar2,
    flags IN number) return number,
    member function ODCIAggregateMerge (self IN OUT stringCat,
    ctx2 IN stringCat) return number
    CREATE OR REPLACE type body stringCat is
    static function ODCIAggregateInitialize(sctx IN OUT stringCat) return
    number is
    begin
    sctx := stringCat('');
    return ODCIConst.Success;
    end;
    member function ODCIAggregateIterate(self IN OUT stringCat, value IN
    varchar2)
    return number is
    begin
    if self.retval is null
    then self.retval:=value;
    else self.retval:=self.retval || ',' || value;
    end if;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateTerminate(self IN stringCat,
    returnValue OUT varchar2,
    flags IN number)
    return number is
    begin
    returnValue := self.retval;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateMerge(self IN OUT stringCat,
    ctx2 IN stringCat) return number is
    begin
    self.retval := self.retval || ctx2.retval;
    return ODCIConst.Success;
    end;
    end;
    CREATE OR REPLACE FUNCTION StrCat (input varchar2) RETURN varchar2
    -- PARALLEL_ENABLE
    AGGREGATE USING StringCat;

    GraphicsConfiguration is an abstract class. You would need to subclass it. From the line of code you posted, it seems like you are going about things the wrong way. What are you trying to accomplish? Shouldn't this question be posted in the Swing or AWT forum?

  • Pivot type query without aggregate function. Transposing

    Hi experts,
    Oracle 11g.
    I have a table (see code example to reproduce), that has a date, a grouping, and the count of that grouping (determined in another query). I need a pivot type query, but, without the aggregate functions. This is just for a report display. I can not seem to figure this one out. Thanks for your help.
    CREATE TABLE temp_task
    AS
       SELECT TO_DATE ('15-NOV-2012') validation_date,
              'GROUP 1' AS group_number,
              42 AS monthly_count
         FROM DUAL
       UNION ALL
       SELECT TO_DATE ('14-DEC-2012') validation_date,
              'GROUP 1' AS group_number,
              33 AS monthly_count
         FROM DUAL
       UNION ALL
       SELECT TO_DATE ('15-NOV-2012') validation_date,
              'GROUP 2' AS group_number,
              10 AS monthly_count
         FROM DUAL
       UNION ALL
       SELECT TO_DATE ('14-DEC-2012') validation_date,
              'GROUP 2' AS group_number,
              32 AS monthly_count
         FROM DUAL
       UNION ALL
       SELECT TO_DATE ('15-NOV-2012') validation_date,
              'GROUP 3' AS group_number,
              7 AS monthly_count
         FROM DUAL
       UNION ALL
       SELECT TO_DATE ('14-DEC-2012') validation_date,
              'GROUP 3' AS group_number,
              9 AS monthly_count
         FROM DUAL;Using only SQL I need to return the following:
    VALIDATION_DATE | GROUP 1 | GROUP 2 | GROUP 3
    11/15/2012 | 42 | 10 | 7
    12/14/2012 | 33 | 32 | 9

    Hi
    You always need to use an aggregate function while pivoting.
    Even if you don't really need any aggregation, that is, when what you see in the table is what you'll get in the result set, you still have to use an aggregate function. If there will only be one value contrinuting to each cell, then you can use MIN or MAX. It won't matter which; since there's only 1 value, that value will be the highest of the 1, and it will also be the lowest. For NUMBER columns, you could also use SUM or AVG.
    SELECT       *
    FROM       temp_task
    PIVOT       ( MIN (monthly_count)
             FOR group_number IN ( 'GROUP 1'
                                 , 'GROUP 2'
                        , 'GROUP 3'
    ORDER BY  validation_date
    ; Output:
    VALIDATION_  'GROUP 1'  'GROUP 2'  'GROUP 3'
    15-Nov-2012         42         10          7
    14-Dec-2012         33         32          9It sounds like you're doing real aggregation someplace, to get monthly_count. Maybe it would be simpler and more efficient to do the pivoting at that point. What is the big picture here? Post some sample data as it is before you compute monthly_count, and the results you want from that data (if different from what you've already posted), and then let's see if we can't aggregte it and pivot it at the same time.

  • The value returned from the load function is not of type numeric  errors after migration to Coldfusion 11

    I am currently testing our website with CF11. It is currently working with CF8 however after migrating it to a new server running CF11 I have encountered the following error.
    The value returned from the load function is not of type numeric.
    The error occurred in
    D:/Applications/CFusion/CustomTags/nec/com/objects/address.cfc: line 263
    Called from D:/Applications/CFusion/CustomTags/nec/com/objects/contact.cfc: line 331
    Called from D:/Applications/CFusion/CustomTags/nec/com/objects/user.cfc: line 510
    Called from D:/Applications/CFusion/CustomTags/nec/com/objects/user.cfc: line 1675
    Called from D:/website/NECPhase2/action.validate.cfm: line 54
    261 : <cfif isNumeric(get.idCountry)>
    262 : <cfset rc = this.objCountry.setID(get.idCountry)>
    263 : <cfset rc = this.objCountry.load()>
    264 : </cfif>
    265 : <cfset this.sPostcode = get.sPostcode>
    Have there been any changes between CF8 and CF11 that could  cause this error?
    Does anyone have ideas?

    This is the code in file object file country.cfc (nec.com.objects.country):
    <cfcomponent displayname="Country object" hint="This is a Country object, it allows you to access and set values in the Country.">
    <!---
    // Construct this object
    --->
    <cfset this.objFunctions = CreateObject( 'component', 'nec.com.system.functions' )>
    <cfscript>
      this.idCountryID = 0;
      this.sCountryName = "";
      this.sISOCode = "";
      this.sDHLCode = "";
      this.iErrorID = "";
    </cfscript>
    <!---
    // The following functions are the setters and getters. offering us a better way to get
    // at the contents of the object
    --->
    <!---
    // Getters
    --->
    <cffunction name="getID" displayname="Get ID" returntype="numeric" output="false" hint="This returns the ID of the current item.">
      <cfreturn this.idCountryID>
    </cffunction>
    <cffunction name="getsCountryName" displayname="Get sCountryName" returntype="string" output="false" hint="This gets the sCountryName value of this item.">
      <cfreturn this.sCountryName>
    </cffunction>
    <cffunction name="getsISOCode" displayname="Get sISOCode" returntype="string" output="false" hint="This gets the sISOCode value of this item.">
      <cfreturn this.sISOCode>
    </cffunction>
    <cffunction name="getsDHLCode" displayname="Get sDHLCode" returntype="string" output="false" hint="This gets the sDHLCode value of this item.">
      <cfreturn this.sDHLCode>
    </cffunction>
    <cffunction name="iError" displayname="Get iError" returntype="numeric" output="false" hint="This returns the iError of the current item.">
      <cfreturn this.iError>
    </cffunction>
    <!---
    // Setters
    --->
    <cffunction name="setID" displayname="Set ID" returntype="boolean" output="false" hint="This sets the ID value of this item.">
      <cfargument name="idCountryID" required="true" type="numeric" displayname="ID" hint="The ID to use.">
      <cfset this.idCountryID = arguments.idCountryID>
      <cfreturn true>
    </cffunction>
    <cffunction name="setsCountryName" displayname="Set sCountryName" returntype="boolean" output="false" hint="This sets the sCountryName value of this item.">
      <cfargument name="sCountryName" required="true" type="string" displayname="sCountryName" hint="The sCountryName to use.">
      <cfset this.sCountryName = arguments.sCountryName>
      <cfreturn true>
    </cffunction>
    <cffunction name="setsISOCode" displayname="Set sISOCode" returntype="boolean" output="false" hint="This sets the sISOCode value of this item.">
      <cfargument name="sISOCode" required="true" type="string" displayname="sISOCode" hint="The sISOCode to use.">
      <cfset this.sISOCode = arguments.sISOCode>
      <cfreturn true>
    </cffunction>
    <cffunction name="setsDHLCode" displayname="Set sDHLCode" returntype="boolean" output="false" hint="This sets the sDHLCode value of this item.">
      <cfargument name="sDHLCode" required="true" type="string" displayname="sDHLCode" hint="The sDHLCode to use.">
      <cfset this.sDHLCode = arguments.sDHLCode>
      <cfreturn true>
    </cffunction>
    <!---
    // Clear, to empty out the contents of this object
    --->
    <cffunction name="clear" displayname="Clear items Details" returntype="boolean" output="false" hint="Clears out all of the items details.">
      <cfscript>
       this.sCountryName = "";
       this.sISOCode = "";
       this.sDHLCode = "";
       this.iErrorID = "";
      </cfscript>
      <cfreturn true>
    </cffunction>
    <!---
    // The following functions deal with the load, save and deleting of objects
    --->
    <!---
    // Load
    --->
    <cffunction name="load" displayname="Load items details" returntype="numeric" output="false" hint="This loads in all the information about an item.">
      <cfset rc = this.clear()>
      <!---
      // First of all we need to get the name of the data source we are going to be using
      --->
      <cfscript>
      objDS = CreateObject("component","nec.com.system.settings");
      sDatasource = objDS.getDatasource();
    </cfscript>
      <!---
      // Check to see if it exists
      --->
      <cftry>
       <cfquery name="checkID" datasource="#sDatasource#">
        SELECT idCountryID
        FROM tblCountry
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("load: checkID: '#this.idCountryID#' #cfcatch.detail#");
        </cfscript>
        <cfset this.iErrorID = iErrorID>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfif not checkID.recordCount>
       <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         if(isDefined("session.afr")){
          whichOne = "#session.afr.getsAFRNumber()#";
         } else {
          whichOne = "";
         iErrorID = objError.addError("A Country with that id doesn't exists.[#this.idCountryID#][#whichOne#]");
        </cfscript>
       <cfset this.iErrorID = iErrorID>
       <cfreturn iErrorID>
      </cfif>
      <!---
      // If we got past all then then load in the details
      --->
      <cftry>
       <cfquery name="get" datasource="#sDatasource#">
        SELECT idCountryID, RTRIM(sCountryName) as sCountryName, RTRIM(sISOCode) as sISOCode, RTRIM(sDHLCode) as sDHLCode
        FROM tblCountry
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("load: get: #cfcatch.detail#");
        </cfscript>
        <cfset this.iErrorID = iErrorID>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfset this.idCountryID = get.idCountryID>
      <cfset this.sCountryName = get.sCountryName>
      <cfset this.sISOCode = get.sISOCode>
      <cfset this.sDHLCode = get.sDHLCode>
      <cfset this.iErrorID = "">
      <cfreturn true>
    </cffunction>
    <!---
    // Save
    --->
    <cffunction name="save" displayname="Save items Details" returntype="numeric" output="false" hint="Saves (to some source) the current details for the ID of the item.">
      <!---
      // First of all we need to get the name of the data source we are going to be using
      --->
      <cfscript>
      objDS = CreateObject("component","nec.com.system.settings");
      sDatasource = objDS.getDatasource();
    </cfscript>
      <!---
      // Now check to see if ithat ID exists
      --->
      <cftry>
       <cfquery name="checkID" datasource="#sDatasource#">
        SELECT idCountryID
        FROM tblCountry
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("save: checkID: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <!---
      // If it doesn't exist, then add the record, otherwise update the record
      --->
      <cfif not checkID.recordCount>
       <cfreturn this.add()>
      <cfelse>
       <cfreturn this.update()>
      </cfif>
    </cffunction>
    <!---
    // Add
    --->
    <cffunction name="add" displayname="Add Country" returntype="numeric" output="false" hint="This adds a Country.">
      <!---
      // Check to see if that a different item isn't already using the same unique details
      --->
      <cftry>
       <cfquery name="checkUnique" datasource="#sDatasource#">
        SELECT idCountryID
        FROM tblCountry
        WHERE sCountryName = '#this.objFunctions.scrubText(this.sCountryName)#'
        OR sISOCOde = '#this.objFunctions.scrubText(this.sISOcode)#'
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("add: checkUnique: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfif checkUnique.recordCount>
       <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("A Country with that name or ISO code already exists. idCountryID=#checkUnique.idCountryID#");
        </cfscript>
       <cfreturn iErrorID>
      </cfif>
      <cftry>
       <cfquery name="add" datasource="#sDatasource#">
        SET nocount on
        INSERT INTO tblCountry(sCountryName, sISOCode, sDHLCode)
        VALUES('#this.objFunctions.scrubText(this.sCountryName)#','#this.objFunctions.scrubText(t his.sISOCode)#','#this.objFunctions.scrubText(this.sDHLCode)#')
        SELECT @@identity as autoID
        SET nocount off  
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("add: add: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfreturn add.autoID>
    </cffunction>
    <!---
    // Update
    --->
    <cffunction name="update" displayname="Update Country" returntype="numeric" output="false" hint="This updates a Country record.">
      <!---
      // Check to see if that a different item isn't already using the same unique details
      --->
      <cftry>
       <cfquery name="checkUnique" datasource="#sDatasource#">
        SELECT idCountryID
        FROM tblCountry
        WHERE (sCountryName = '#this.objFunctions.scrubText(this.sCountryName)#'
        OR sISOCOde = '#this.objFunctions.scrubText(this.sISOcode)#')
        AND idCountryID <> #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("update: checkUnique: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfif checkUnique.recordCount>
       <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("Another Country with that name already exists. idCountryID=#checkUnique.idCountryID#");
        </cfscript>
       <cfreturn iErrorID>
      </cfif>
      <!---
      // Attempt to update the record to the datasource
      // if this fails for any reason then we submit an error message
      // to the error component and return the ID of the error
      --->
      <cftry>
       <cfquery name="update" datasource="#sDatasource#">
        UPDATE tblCountry
        SET sCountryName = '#this.objFunctions.scrubText(this.sCountryName)#',
        sISOCode = '#this.objFunctions.scrubText(this.sISOCode)#',
        sDHLCode = '#this.objFunctions.scrubText(this.sDHLCode)#'
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("update: update: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfreturn this.idCountryID> 
    </cffunction>
    <!---
    // Delete
    --->
    <cffunction name="delete" displayname="Delete Country" returntype="numeric" output="false" hint="This deletes a Country record.">
      <!---
      // First of all we need to get the name of the data source we are going to be using
      --->
      <cfscript>
      objDS = CreateObject("component","nec.com.system.settings");
      sDatasource = objDS.getDatasource();
    </cfscript>
      <!---
      // Now check to see if ithat ID exists
      --->
      <cftry>
       <cfquery name="checkID" datasource="#sDatasource#">
        SELECT idCountryID
        FROM tblCountry
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("delete: checkID: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfif not checkID.recordCount>
       <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("A Country with that id doesn't exists, delete failed.");
        </cfscript>
       <cfreturn iErrorID>
      </cfif>
      <!---
      // Now check to see if there are any dependancies, if so we can't delete the item
      --->
      <cftry>
       <cfquery name="checkDependancies" datasource="#sDatasource#">
        SELECT idCountry
        FROM tblAddress
        WHERE idCountry = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("delete: checkDependancies: idCountry: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfif checkDependancies.recordCount>
       <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("That Country is being used by an address, delete failed.");
        </cfscript>
       <cfreturn iErrorID>
      </cfif>
      <!---
      // Now attempt to remove the record.
      // if this fails for any reason then we submit an error message
      // to the error component and return the ID of the error
      --->
      <cftry>
       <cfquery name="delete" datasource="#sDatasource#">
        DELETE FROM tblCountry
        WHERE idCountryID = #this.idCountryID#
       </cfquery>
       <cfcatch>
        <cfscript>
         objError = CreateObject("component","nec.com.system.errors");
         iErrorID = objError.addError("delete: delete: #cfcatch.detail#");
        </cfscript>
        <cfreturn iErrorID>
       </cfcatch>
      </cftry>
      <cfreturn this.idCountryID>
    </cffunction>
    </cfcomponent>

  • ResultSet Type - Aggregate Functions

    I'm not so sure...but whenever i use a scrollable resultset, i don't seem to be able to use the 5 aggregate functions....
    SUM COUNT MIN MAX AVG...all of them fail...
    i keep getting invalid cursor state...
    but after i changed the resultset type back to ResultSet.TYPE_FORWARD_ONLY..... it works fine....
    is there any way to use these 5 functions together with the scrollable resultset?
    thank you... :)

    Why do you need it to be scrollable? You can't update such a result-set, so I don't see the need for reading any of its records more than once.

  • Why doesn't PIVOT clause work with COLLECT aggregate function in 11g ?

    Hello all !
    I am really puzzled as to what is considered an aggregate function in the context of the PIVOT clause in 11g.
    I have been toying with quite a few things related to collections lately and this arose as an aside :
    CREATE TABLE TEST_COLL
       NODE_ID    VARCHAR2(15 CHAR) NOT NULL,
       NODE_VALUE VARCHAR2(45 CHAR) NOT NULL,
       NODE_LEVEL NUMBER(1)         NOT NULL
    CREATE OR REPLACE TYPE TREE_NODE AS OBJECT
       NODE_KEY  VARCHAR2( 15 CHAR),
       NODE_NAME VARCHAR2(127 CHAR)
    CREATE OR REPLACE TYPE TREE_NODES AS TABLE OF TREE_NODE NOT NULL;At this stage I am sure we all agree that the query
    SELECT NODE_LEVEL,
           CAST(COLLECT(TREE_NODE(NODE_ID, NODE_VALUE)) AS TREE_NODES) AS NODES
      FROM TEST_COLL
    GROUP BY NODE_LEVEL;is perfectly valid as the COLLECT function is an aggregate function according to the [Official Documentation|http://docs.oracle.com/cd/E11882_01/server.112/e10592/functions031.htm#i1271564]
    But then, one of the following two queries should work
    SELECT CAST(REGION_NODES     AS TREE_NODES) AS REGIONS,
           CAST(DEPARTMENT_NODES AS TREE_NODES) AS DEPARTMENTS,
           CAST(AREA_NODES       AS TREE_NODES) AS AREAS,
           CAST(CENTRE_NODES     AS TREE_NODES) AS CENTRES
      FROM (SELECT NODE_LEVEL, TREE_NODE(NODE_ID, NODE_VALUE) AS NODE
              FROM TREE_COLL
    PIVOT (COLLECT(NODE) FOR NODE_LEVEL IN (1 AS REGION_NODES,
                                             2 AS DEPARTMENT_NODES,
                                             3 AS AREA_NODES,
                                             4 AS CENTRE_NODES
    or (better)
    SELECT REGION_NODES     AS REGIONS,
           DEPARTMENT_NODES AS DEPARTMENTS,
           AREA_NODES       AS AREAS,
           CENTRE_NODES     AS CENTRES
      FROM (SELECT NODE_LEVEL, TREE_NODE(NODE_ID, NODE_VALUE) AS NODE
              FROM TREE_COLL
    PIVOT (CAST(COLLECT(NODE) AS TREE_NODES) FOR NODE_LEVEL IN (1 AS REGION_NODES,
                                                                 2 AS DEPARTMENT_NODES,
                                                                 3 AS AREA_NODES,
                                                                 4 AS CENTRE_NODES
           );yet, both fail with
    ORA-56902: expect aggregate function inside pivot operationInvestigating further, I found the same behaviour when using XMLAGG as the aggregate function in the PIVOT clause.
    Is this normal ? And if it is, is there any other way to achieve the result I was anticipating ?
    My version is
    SQL> SELECT BANNER FROM V$VERSION;
    BANNER
    Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
    PL/SQL Release 11.2.0.3.0 - Production
    CORE    11.2.0.3.0      Production
    TNS for 64-bit Windows: Version 11.2.0.3.0 - Production
    NLSRTL Version 11.2.0.3.0 - ProductionThanks in advance
    Best Regards
    Philip

    Most likely a bug. But you can bypass it by using any other aggregate making sure group consists of a single row and apply collect to a pivoted value. Yes, the cost is double aggregation. And also there is another cost - you would need to create MAP member function otherwise aggreations like MAX/MIN, etc. will not work:
    CREATE OR REPLACE TYPE TREE_NODE AS OBJECT
       NODE_KEY  VARCHAR2( 15 CHAR),
       NODE_NAME VARCHAR2(127 CHAR),
       map member function f return varchar2
    Type created.
    CREATE OR REPLACE TYPE BODY TREE_NODE AS
      map member function f return varchar2 is
      begin
         return NODE_NAME;
      end f;
    end;
    Type body created.
    CREATE OR REPLACE TYPE TREE_NODES AS TABLE OF TREE_NODE NOT NULL
    Type created.
    SQL> select  *
      2    from  test_coll
      3  /
    NODE_ID NODE_VALUE NODE_LEVEL
    1       A                   1
    2       B                   2
    3       C                   3
    4       D                   4
    5       E                   1
    6       F                   2
    7       G                   3
    8       H                   4
    8 rows selected.
    SQL> Now:
    SELECT CAST(COLLECT(REGION_NODES)     AS TREE_NODES) AS REGIONS,
           CAST(COLLECT(DEPARTMENT_NODES) AS TREE_NODES) AS DEPARTMENTS,
           CAST(COLLECT(AREA_NODES)       AS TREE_NODES) AS AREAS,
           CAST(COLLECT(CENTRE_NODES)     AS TREE_NODES) AS CENTRES
      FROM (
            SELECT  ROWID RID,
                    NODE_LEVEL,
                    TREE_NODE(NODE_ID, NODE_VALUE) AS NODE
              FROM  TEST_COLL
    PIVOT (MAX(NODE) FOR NODE_LEVEL IN (
                                         1 AS REGION_NODES,
                                         2 AS DEPARTMENT_NODES,
                                         3 AS AREA_NODES,
                                         4 AS CENTRE_NODES
    REGIONS(NODE_KEY, NODE_NAME)                         DEPARTMENTS(NODE_KEY, NODE_NAME)                     AREAS(NODE_KEY, NODE_NAME)                           CENTRES(NODE_KEY, NODE_NAME)
    TREE_NODES(TREE_NODE('1', 'A'), TREE_NODE('5', 'E')) TREE_NODES(TREE_NODE('6', 'F'), TREE_NODE('2', 'B')) TREE_NODES(TREE_NODE('7', 'G'), TREE_NODE('3', 'C')) TREE_NODES(TREE_NODE('8', 'H'), TREE_NODE('4', 'D'))
    SQL> SY.

  • How can I use User-Defined Aggregate Functions in Timesten 11? such as ODCI

    Hi
    we are using Timesten 11 version and as per the documentation, it doesn't support User-Defined Aggregate Functions.
    So we are looking for alternatives to do it. Could you please provide your expert voice on this.
    Thanks a lot.
    As the following:
    create or replace type strcat_type as object (
    cat_string varchar2(32767),
    static function ODCIAggregateInitialize(cs_ctx In Out strcat_type) return number,
    member function ODCIAggregateIterate(self In Out strcat_type,value in varchar2) return number,
    member function ODCIAggregateMerge(self In Out strcat_type,ctx2 In Out strcat_type) return number,
    member function ODCIAggregateTerminate(self In Out strcat_type,returnValue Out varchar2,flags in number) return
    number
    How can I use User-Defined Aggregate Functions in Timesten 11? such as ODCIAggregateInitialize ?

    Dear user6258915,
    You absolutely right, TimesTen doesnt support object types (http://docs.oracle.com/cd/E13085_01/doc/timesten.1121/e13076/plsqldiffs.htm) and User-Defined Aggregate Functions.
    Is it crucial for your application? Could you rewrite this functionality by using standart SQL or PL/SQL?
    Best regards,
    Gennady

  • Aggregate functions for internal table.

    Hi Gurus,
    I'm just wondering whether we can use aggregate functions for internal table. I wanted to know the max value for a particular column in my internal table. How can I achieve this easily and quickly.
    Thanks,
    David.

    sort the table on which you want the maximum value and read it. Please find below example code.
    TYPES : BEGIN OF ty_mvke,
            matnr TYPE mvke-matnr,
            vkorg TYPE mvke-vkorg,
            vtweg TYPE mvke-vtweg,
           AUMNG type mvke-AUMNG,
            END OF ty_mvke.
    DATA : wa_mvke TYPE ty_mvke,
           it_mvke TYPE STANDARD TABLE OF ty_mvke.
    data : temp_AUMNG type AUMNG.
    START-OF-SELECTION.
      SELECT matnr vkorg vtweg AUMNG FROM mvke INTO
            table it_mvke.
    sort it_mvke by AUMNG.
    read TABLE it_mvke into wa_mvke INDEX 1.
    if sy-subrc = 0.
    move wa_mvke-AUMNG to temp_AUMNG.
    write : temp_AUMNG.
    endif.
    Thanks,
    Sreekala.

  • Select into aggregate function

    Hi,
    I have the following PL/SQL block that I am testing. The block reads a list of values from a local file and inserts the values into a select statement that uses an aggregate function. Here is my code:
    DECLARE
    f utl_file.file_type;
    n COLa%TYPE; --holds values from the file
    v COLb%TYPE; --holds value returned by select statement
    BEGIN
    f := utl_file.fopen(dir,file.txt,'R');
    loop -- loop through file
         utl_file.get_line(f,n);
         if length(n) <> 0 then
              SELECT max(A0.COLa) into v
              FROM (SELECT AOB.COLa, A0.COLb
              FROM TAB1 A0,TAB2 A0B
              WHERE (A0.PK=A0B.PK) and A0B.COLa = n) A0;          
              IF SQL%rowcount = 0 THEN
                   dbms_output.put_line('no rows);
              else
                   dbms_output.put_line(v);
              end if;                    
         end if;     
    end loop;
         utl_file.fclose(f);     
    end;
    Here is the error I get:
    declare
    ERROR at line 1:
    ORA-01403: no data found
    ORA-06512: at "SYS.UTL_FILE", line 98
    ORA-06512: at "SYS.UTL_FILE", line 656
    ORA-06512: at line 12
    I checked the database for the first couple of values in the list and got rows. I also ran a simple PL/sql code to print values in the file successfully. So I dont know why it is returning no data found. From what I understand select into statement using aggregate functions will never raise this exception, so why I am getting this error?
    Thanks.

    Hi,
    Actually, the SELECT ... INTO isn't the problem here.
    Look at the error message:
    ERROR at line 1:
    ORA-01403: no data found
    ORA-06512: at "SYS.UTL_FILE", line 98
    ORA-06512: at "SYS.UTL_FILE", line 656
    ORA-06512: at line 12The error is ocurring inside utl_file, which is being called at line 12 of your code. (That must be
    utl_file.get_line(f,n);)
    Utl_file.get_line raises NO_DATA_FOUND when it reaches the end of the file. (If it didn't you'd have an infinite loop, since your code doesn't have any exit strategy.)
    You can put the call to get_line in its won BEGIN-EXCEPTION-END block, and trap the NO_DATA_FOUND error.
    For example:
    end_of_file := 0;
    WHILE  end_of_file = 0;
    loop -- loop through file
        BEGIN
            utl_file.get_line(f,n);
            if length(n) != 0 then          -- Use !=, because you can't post &lt;&gt; on this site
                SELECT  max(A0B.COLa)     -- No sub-query needed
                into    v
                FROM    TAB1 A0
                ,         TAB2 A0B
                WHERE   (A0.PK   = A0B.PK)
                and         A0B.COLa = n;
                IF SQL%rowcount = 0 THEN     -- Not needed: SELECT MAX ... without GROUP BY always returns 1 row
                    dbms_output.put_line('no rows);
                else
                    dbms_output.put_line(v);
                end if;
            end if;
        EXCEPTION
            WHEN  NO_DATA_FOUND
            THEN
                end_of_file = 1;
        END;
    end loop;Edited by: Frank Kulash on Jul 17, 2009 2:51 PM

  • User-Defined Aggregate Function in oracle

    Somebody knows if in oracle 10g is possible to create a User-Defined Aggregate Function?
    Sometingh like my_sum, that aggregate the values in a way that i want...
    select manager, my_sum(salary)
    group by manager
    In internet i've found rellay notingh for oracle 10g...can somebody help me? Thank's in advance!

    Thank's to everybody!!! I've made my custom function sum_distinct
    create or replace type AggregateCD as object
    (  nb                   number,
         ListOfDistinctValue  clob,
        static               function ODCIAggregateInitialize(sctx IN OUT AggregateCD) return number,
        member               function ODCIAggregateIterate(self IN OUT AggregateCD, value IN VARCHAR2) return number,
         member               function ODCIAggregateTerminate(self IN AggregateCD, returnValue OUT number, flags IN number) return number,
        member               function ODCIAggregateMerge(self IN OUT AggregateCD, ctx2 IN AggregateCD) return number
    create or replace type body AggregateCD is
       static function ODCIAggregateInitialize(sctx IN OUT AggregateCD) return number is
         begin
             sctx := AggregateCD(0,null);
             return ODCIConst.Success;
        end;
        member function ODCIAggregateIterate(self IN OUT AggregateCD, value IN VARCHAR2) return number is
            ListOfValue CLOB:=self.ListOfDistinctValue ;
         begin
             self.nb:=self.nb+to_number(substr(value , INSTR(value, ';', 1, 1)+1 ,length(value)));
            return ODCIConst.Success;
        end;
        member function ODCIAggregateTerminate(self IN AggregateCD, returnValue OUT number, flags IN number) return number is
         begin
              returnValue := self.nb;
              return ODCIConst.Success;
        end;
         member function ODCIAggregateMerge(self IN OUT AggregateCD, ctx2 IN AggregateCD) return number is
         begin
             self.nb := ctx2.nb;
             return ODCIConst.Success;
        end;
      end;
    CREATE OR REPLACE FUNCTION sum_distinct (input VARCHAR2) RETURN number
      PARALLEL_ENABLE AGGREGATE USING AggregateCD;you can use so:
    select sum_distinct(distinct t.primary_key||';'||t.import)
    from table1 t, table2_with_bad_join
    it's the same of
    select sum(t.import)
    from table 1

  • How to pass a large value to a parameter of a service

    Hi Everyone,
    I need to execute service GET_SEARCH_RESULTS and want to provide values to its parameter QueryText. I am calling the service in the following manner:
    http://localhost/idc/idcplg?IdcService=GET_SEARCH_RESULTS&QueryText=<$keyTagID$>&ftx=&AdvSearch=True&SortField=xAvgRating&ResultCount=5
    hence passing <$keyTagID$> to QueryText. Now in my case, this variable <$keyTagID$> is becoming very large consequently making the whole of above URL very big. Its crossing the permissible limit of 2038 characters by Internet Explorer. Thus error 'URL too large' comes when I am executing the service.
    Please suggest me how to execute the service 'GET_SEARCH_RESULTS', so that I can provide a large value to the parameter QueryText. I thought of making use IdocScript function 'executeService', but so far as I know this function accepts only one argument which is service name. Thus how to provide values to parameters of a service with 'executeService' function?
    Thanks & Regards,
    Ashish Gupta

    Hi,
    To send large arguments over HTTP you have to post them, basically setting up a form similar to this:
    <form action="<$HttpCgiPath$>" method="POST">
    <input type="hidden" name="IdcService" value="GET_SEARCH_RESULTS"/>
    <input type="hidden" name="QueryText" value="<$keyTagId$>"/>
    <input type="hidden" name="ftx" value=""/>
    <input type="hidden" name="AdvSearch" value="True"/>
    <input type="hidden" name="SortField" value="xAvgRating"/>
    <input type="hidden" name="ResultCount" value="5"/>
    <input type="submit" name="submit" value="submit"/>
    </form>
    I'm not sure how much that helps if your users are currently just clicking a link. You could hide the form somewhere and have your link execute a javascript function which then posts the form.
    David

  • 8i personal : error when Create user defined aggregate function

    Hi,
    I have problem on creating user defined aggregate function.
    I try to create the sample aggregate function "SecondMax" from 9i developer guide(append at the end of this post).
    It's work to create object type and the type body, but
    there is error when I create the aggregate function..
    "CREATE FUNCTION SecondMax (input NUMBER) RETURN NUMBER
    PARALLEL_ENABLE AGGREGATE USING SecondMaxImpl;"
    I am using 8i personal now.. is that the syntax of create function in 9i is different from that in 8i?
    Example: Creating and Using a User-Defined Aggregate
    This example illustrates creating a simple user-defined aggregate function SecondMax() that returns the second-largest value in a set of numbers.
    Creating SecondMax()
    Implement the type SecondMaxImpl to contain the ODCIAggregate routines.
    create type SecondMaxImpl as object
    max NUMBER, -- highest value seen so far
    secmax NUMBER, -- second highest value seen so far
    static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl)
    return number,
    member function ODCIAggregateIterate(self IN OUT SecondMaxImpl,
    value IN number) return number,
    member function ODCIAggregateTerminate(self IN SecondMaxImpl,
    returnValue OUT number, flags IN number) return number,
    member function ODCIAggregateMerge(self IN OUT SecondMaxImpl,
    ctx2 IN SecondMaxImpl) return number
    Implement the type body for SecondMaxImpl.
    create or replace type body SecondMaxImpl is
    static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl)
    return number is
    begin
    sctx := SecondMaxImpl(0, 0);
    return ODCIConst.Success;
    end;
    member function ODCIAggregateIterate(self IN OUT SecondMaxImpl, value IN number)
    return number is
    begin
    if value > self.max then
    self.secmax := self.max;
    self.max := value;
    elsif value > self.secmax then
    self.secmax := value;
    end if;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateTerminate(self IN SecondMaxImpl, returnValue OUT
    number, flags IN number) return number is
    begin
    returnValue := self.secmax;
    return ODCIConst.Success;
    end;
    member function ODCIAggregateMerge(self IN OUT SecondMaxImpl, ctx2 IN
    SecondMaxImpl) return number is
    begin
    if ctx2.max > self.max then
    if ctx2.secmax > self.secmax then
    self.secmax := ctx2.secmax;
    else
    self.secmax := self.max;
    end if;
    self.max := ctx2.max;
    elsif ctx2.max > self.secmax then
    self.secmax := ctx2.max;
    end if;
    return ODCIConst.Success;
    end;
    end;
    Create the user-defined aggregate.
    CREATE FUNCTION SecondMax (input NUMBER) RETURN NUMBER
    PARALLEL_ENABLE AGGREGATE USING SecondMaxImpl;
    Using SecondMax()
    SELECT SecondMax(salary), department_id
    FROM employees
    GROUP BY department_id
    HAVING SecondMax(salary) > 9000;

    This could be a x64/x86 problem. Try following this thread
    [GetCompanyService|GetCompanyService] and recompile your code for the platform you need.

  • Aggregate Functions in SELECT

    Hi Friends,
      Is it possible to have an aggregate function while using Inner join and GROUP BY? Its not working for me.
    Prompt replies would be rewarded.
    Thanks in advance.
    Regards
    Tamilarasan.
    Message was edited by: Tamilarasan Lakshmanan

    I'm not sure what you mean by 'not working', but you can try something like:
    * select data: parked documents in value type 54 (invoice) --------
      select  fmifiit~knbelnr bkpf~bstat
          count( distinct fmifiit~fmbelnr )
       into (wa_error-belnr, wa_error-bstat, wa_error-count)
       from fmifiit inner join bkpf
          on ( fmifiit~bukrs = bkpf~bukrs and
               fmifiit~kngjahr = bkpf~gjahr and
               fmifiit~knbelnr = bkpf~belnr )
          where fmifiit~knbelnr in s_belnr
            and fmifiit~bukrs = p_bukrs
            and fmifiit~kngjahr = p_gjahr
            and ( fmifiit~wrttp = '54' or
                  fmifiit~wrttp = '57' or
                  fmifiit~wrttp = '66' )
            and bkpf~bukrs = p_bukrs
            and bkpf~gjahr = p_gjahr
            and bkpf~belnr in s_belnr
            and bkpf~budat in s_budat
            and ( bkpf~bstat = 'V' or bkpf~bstat = 'W' or bkpf~bstat = 'Z' )
          group by fmifiit~knbelnr
                   bkpf~bstat
          order by fmifiit~knbelnr.
    Rob

  • Problem with my aggregate function

    Hello there,
    I tried to build my own string aggregate function but I've a troubles when I'm using it into my query. When I'm using it, it writes ORA904, whereas this idenfifier exists. Do you know what's wrong ?
    here my aggregate function :
    create or replace FUNCTION aggme (query_in in VARCHAR2) RETURN VARCHAR2 IS
        incoming    varchar2(4000);
        hold_result varchar2(4000);
        c sys_refcursor;
    Begin
        open c for query_in;
        loop
            fetch c into incoming;
            exit when c%notfound;
            hold_result := hold_result||','||incoming;
        end loop;
        return ltrim(hold_result,',');
    END;and here my query by using my aggregate function aggme:
    select
      RES.LASTNAME as "LASTNAME",
      RES.FIRSTNAME as "FIRSTNAME",
      aggme('select NAME from PATHOLOGY where ID= RES.PATHOLOGY_ID') as "PATHOLOGY"
    from
      TBK_RESOURCE RES

    Mustafa KALAYCI wrote:
    I think you wanted to do this:
    select
    RES.LASTNAME as "LASTNAME",
    RES.FIRSTNAME as "FIRSTNAME",
    aggme('select NAME from PATHOLOGY where ID=' || RES.PATHOLOGY_ID) as "PATHOLOGY"
    from
    TBK_RESOURCE RESby the way this is a very very bad idea doing like that. you should look for WM_CONCAT (for db version 11.1 or lower)No. Nobody should use WM_CONCAT. It's an undocumented function that is not supported by Oracle and may be changed in future versions without notice.
    All Oracle experts say not to use it, including Tom Kyte... Re: DISTINCT not working with  wmsys.wm_concat
    Below 11gR2, you should use SYS_CONNECT_BY_PATH, or a user defined function, including user defined aggregate functions such as the following example, which aggregates strings into a clob as a result...
    create or replace type clobagg_type as object
      text clob,
      static function ODCIAggregateInitialize(sctx in out clobagg_type) return number,
      member function ODCIAggregateIterate(self in out clobagg_type, value in clob) return number,
      member function ODCIAggregateTerminate(self in clobagg_type, returnvalue out clob, flags in number) return number,
      member function ODCIAggregateMerge(self in out clobagg_type, ctx2 in clobagg_type) return number
    create or replace type body clobagg_type is
      static function ODCIAggregateInitialize(sctx in out clobagg_type) return number is
      begin
        sctx := clobagg_type(null) ;
        return ODCIConst.Success ;
      end;
      member function ODCIAggregateIterate(self in out clobagg_type, value in clob) return number is
      begin
        self.text := self.text || value ;
        return ODCIConst.Success;
      end;
      member function ODCIAggregateTerminate(self in clobagg_type, returnvalue out clob, flags in number) return number is
      begin
        returnValue := self.text;
        return ODCIConst.Success;
      end;
      member function ODCIAggregateMerge(self in out clobagg_type, ctx2 in clobagg_type) return number is
      begin
        self.text := self.text || ctx2.text;
        return ODCIConst.Success;
      end;
    end;
    create or replace function clobagg(input clob) return clob
      deterministic
      parallel_enable
      aggregate using clobagg_type;
    SQL> select trim(',' from clobagg(ename||',')) as enames from emp;
    ENAMES
    SMITH,ALLEN,WARD,JONES,MARTIN,BLAKE,CLARK,SCOTT,KING,TURNER,ADAMS,JAMES,FORD,MILLER
    SQL> ed
    Wrote file afiedt.buf
      1  with t as
      2    (select 'PFL' c1, 0 c2,110 c3 from dual union all
      3     select 'LHL', 0 ,111 from dual union all
      4     select 'PHL', 1, 111 from dual union all
      5     select 'CHL', 2, 111 from dual union all
      6     select 'DHL', 0, 112 from dual union all
      7     select 'VHL', 1, 112 from dual union all
      8     select 'CPHL', 0, 114 from dual union all
      9     select 'WDCL', 1, 114 from dual union all
    10     select 'AHL' ,2 ,114 from dual union all
    11     select 'NFDL', 3, 114 from dual)
    12  --
    13  -- end of test data
    14  --
    15  select trim(clobagg(c1||' ')) as c1, c3
    16  from (select * from t order by c3, c2)
    17  group by c3
    18* order by c3
    SQL> /
    C1                                     C3
    PFL                                   110
    LHL CHL PHL                           111
    DHL VHL                               112
    CPHL AHL NFDL WDCL                    114

Maybe you are looking for