Function vs Join

I have a dashboard query from a developer that joins 7 tables and gets data from 5. I have rewritten the query using 5 functions and select data from the main table. Explain plan shows the second query as less costly but sometimes seems longer. Is there a good document that explains the difference and when it is best to use a join and when to use functions?
Also, I use the functions in the select clause not the where clause but have done some testing there as well. Are functions better in the select or where?
thanks

Joins are almost always going to be faster/cheaper. To the best of my knowledge the optimizer cannot see the cost of a pl/sql function and does not include it in it's consideration of explain plans. I'd go back to a join-based approach and then look for places in the explain plan where the cardinality of a step does not match the actual value you know to be true. Jonathan P. Lewis' book on the optimizer is invaluable here. Good luck.

Similar Messages

  • User Defined Function VS join - Performance....

    Hi All,
    while linking the mulitple table and getting the values ....which one is the best ?
    Joining or User defined function.....
    single row function
    select a.name , get_salary(empid) from emp a;
    Note : get_salary function will return the salary from salary tables.
    Using joins
    select a.name ,b.salary from emp a, salary b
    where a.empid=b.empid;
    which is the performancewise best ?
    also if you give any related document also fine.
    Thanks in advance.
    Edited by: BASKAR NATARAJAN on Jan 6, 2011 10:09 PM

    Don't use such functions for joins. The function itself has to query the salary table. It will run the query against the salary table separately for each row that it reads from the emp table. You will end up with multiple recursive calls and possibly inconsistency in the output. (Imagine what would happen if the salary table were updated and commited while this query was running -- some rows would have been read with the pre-update values and others with the updated values).
    Specifying the join in the query ensures that a single SQL call is executed and provides read consistency across all the rows it reads. And it is much faster, being one single parse and execute.
    Hemant K Chitale
    http://hemantoracledba.blogspot.com

  • Aggregation Function With Joining

    Hi all,
    I've the following SQL Query and I want to add a join with it:
    SELECT Collected_Goods.ProductId, SUM(Collected_Goods.Amount)
    FROM Collected_Goods
    GROUP BY Collected_Goods.ProductIdand I want to replace or add (but replace is better) the Collected_Goods.ProductId with a Products.Name where the product name appears in another table called products. Also I want the aggregation function SUM to work on Collected_Goods.ProductId
    The FK in Collected_Goods to Products is Collected_Goods.ProductId and Products.Id
    Thanks in advance
    Edited by: ZiKaS on Dec 30, 2008 2:05 AM

    The output for the above one is like this
    Collected_Goods.ProductId     |     SUM(Amount)
                                 1           |        60     
                                 2           |        32
                                 .            |         .
                                 .            |         .
                                 .            |         .
    I want it to be something link this
    Products.Name                     |     SUM(Amount)
                                 Milk        |        60     
                                 Butter    |        32
                                 .            |         .
                                 .            |         .
                                 .            |         .                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

  • Can function in join reduce the performace.

    hi,
       i have a function fn_oneortworow it accepts one parameter.
    i have used it in left join as follows
    1)
    select * from T
    left join fn_oneortworow(@a) a on a.id=t.id
    my fear is that it may execute as many times as many rows are there in table "T"
    so i have made the query as follows
    2)
    select * into #temp from join fn_oneortworow(@a)
    select * from T
    left join #temp a on a.id=t.id
    Q1)please tel me that is it correct that in first query function will called as many times as many records are ther in table T?
    Q2)and is second formulation is good or should i use the first one. (to imporve the performance)
    yours sincerely

    It probably will call the function only once.  Since you are always calling it with the same parameter value, SQL knows the the function will always return the same result.  It is easy to check by looking at the estimated execution plan, that will
    tell you how many times SQL believes it will be called.
    Nevertheless, even if it is only called once, I would still do the temp table and load the table with a function call.  Then you know for sure the function is only called once.
    In addition, if the function can return a lot of rows and id can be a primary key to to #temp table, I would explicitly declare the #temp table with id as a primary key.  That will make the join much faster if #temp has many rows.  And if id is
    not a suitable primary key, but #temp has lots of rows, I would create an index on id to speed up the join.
    But the only way to know for sure is to run the possible choices with a realistic set of data and see which method is best.
    Tom

  • Aggregate function and join

    I have three Tables(Emptimesheet,comexpensetable,perexpensestable).I want to show otput something like below,
    EmpID,EmpName,StartDate,EndDate,Total,Chotel,CAirfare,Cfuel,WeeklCompanyExpenses,Percompanyexpenses
    rightnow in the below query I don't have hotel,airfare,fuel.
    select distinct(e.EmpID) ,e.EmpName, e.StartDate,e.EndDate,e.Total,c.WeeklyComtotalExpenses,p.WeeklyPerTotalExpenses
    from EmpTimeSheet e left JOIN ComExpensesTable c on c.CExpID=e.EmpID left join PerExpensesTable p ON p.PExpID=e.EmpID
    Output for Above query .
    EmpID name sd ED Total companEx PerExpense 1 tom 2014-02-02 00:00:00.000 2014-02-08 00:00:00.000 28:30:0 213.00 199.00
    3 nick 2014-03-02 00:00:00.000 2014-03-08 00:00:00.000 15:20:0 16.00 NULL
    4 john 2014-03-23 00:00:00.000 2014-03-29 00:00:00.000 42:0:0 NULL NULL
    5 test 2014-03-09 00:00:00.000 2014-03-15 00:00:00.000 34:15:0 NULL NULL
    6 ema 2014-04-13 00:00:00.000 2014-04-19 00:00:00.000 39:0:0 16.00 NULL
    Output  Emptimesheet
    id empname startdate enddate .. total 1 tom 2014-02-02 00:00:00.000 2014-02-08 00:00:00.000 Thurs 2014-02-06 00:00:00.000 Travel Time 28:30:0
    3 nick 2014-03-02 00:00:00.000 2014-03-08 00:00:00.000 Mon 2014-03-03 00:00:00.000 Onsite/WalkTesting 40:0:0
    4 john 2014-03-23 00:00:00.000 2014-03-29 00:00:00.000 Mon 2014-03-24 00:00:00.000 Onsite/WalkTesting 42:0:0
    5 test 2014-03-09 00:00:00.000 2014-03-15 00:00:00.000 Mon 2014-03-10 00:00:00.000 Travel Time , 34:15:0
    6 ema 2014-04-13 00:00:00.000 2014-04-19 00:00:00.000 Mon 2014-04-14 00:00:00.000 Equipment Testing 39:0:0
    output for ComExpenseTable 
    CExpID airfare hotel weeklycomexpensetable 1 45.00 34.00 213.00
    3 5.00 3.00 16.00
    6 5.00 3.00 16.00
    output  for  Perexpensetable
    PExpID PerExpenseTable1 Sun 2014-02-02 00:00:00.000 199.00
    2 Sun 2014-02-23 00:00:00.000 199.00
    below  query for sum of indivial expense in company table
    select sum(CHotel) as Hotel ,sum(CTransport) as Airfare,sum(CMeals) as Meals,sum(CFuel) as Gas,sum(CTolls),Sum(CParking) as Parking,Sum(CMisc) as Misc ,sum(CMileage) as Mileage from ComExpensesTable where CExpID=1
    Now  I want  to add  sum of hotel,transport ..  to  the below query  .I don't  know how  to do this.Any suggestions please?
    select distinct(e.EmpID) ,e.EmpName, e.StartDate,e.EndDate,e.Total,c.WeeklyComtotalExpenses,p.WeeklyPerTotalExpenses
    from EmpTimeSheet e left JOIN ComExpensesTable c on c.CExpID=e.EmpID left join PerExpensesTable p ON p.PExpID=e.EmpID

    select
    distinct(e.EmpID) ,
    e.EmpName,
    e.StartDate,
    e.EndDate,
    e.Total,
    ee.Hotel,
    ee.Airfare,
    c.WeeklyComtotalExpenses,
    p.WeeklyPerTotalExpenses
    fromEmpTimeSheet e
    left JOIN (select CExpID, sum(CHotel) as Hotel ,sum(CTransport) as Airfare,
    sum(CMeals) as Meals,sum(CFuel) as Gas,sum(CTolls),
    Sum(CParking) as Parking,Sum(CMisc) as Misc ,
    sum(CMileage) as Mileage from ComExpensesTable group by CExpID) cleft join // don't need the "left join" hereon c.CExpID=e.EmpID //error
    left join PerExpensesTable p ON p.PExpID=e.EmpID

  • Function or join

    Hi,
    I have a query where one of the values I want to return is the max(date) for a given event and an account from a table. I wrote a simple function to return this but when I include this in my select statement it's very slow.
    However if I don't use a function and just add the criteria to the where clause in the query it's much faster.
    Can anybody explain this to me?
    Thanks
    Sean

    Sean:
    The performance difference is due to the context switch between SQL and PL/SQL to execute your function, plus the amount of time required to execute your function.
    The function would be executed once for each row in the table, so even if it it only takes 0.01 seconds (which is pretty fast), that means one extra second for every hundred rows in the table compared to a simple select. Additionally, depending on what else is in the WHERE clause, the use of the function may preclude the use of a particular index that would be more efficient.
    HTH
    John

  • Where clause in COUNT function and joining two queries

    I have a table that I am trying to count the number of course passed, and also list the modules passed as well.
    the first problem I am having is what to put in the where variable , so that its not specific to a customer(I can use the query below for a particular customer and a particular course)but I will like a generic query where the result will be distinct in terms
    of user and course like the one below
    select FirstName,LastName,CourseTitle,Noofmodules, count (Coursecompleted) as modulescompleted from EStudentsprogress where Coursecompleted = '1'and EmailAddress = '[email protected]'
    and CourseTitle = 'Microsoft MOS 2010 EXCEL' Group by FirstName, LastName, CourseTitle, Noofmodules ;
    How can i make it list the result as above, whereby i dont specify the email address or course title(trying to get the result for all the clients )
    . Also I have a query that list the courses that is passed by the customer, I will like the column with the list of courses passed be added to the result above, but as a column for each course.
    select FirstName,LastName,CourseTitle, EmailAddress, CourseModule as coursepassed from EStudentsprogress where coursecompleted =1
    cheers

    Do you mean this?
    select FirstName,
    LastName,
    CourseTitle,
    Noofmodules,
    count (Coursecompleted) as modulescompleted,
    STUFF((SELECT ',' + CourseTitle
    FROM EStudentsprogress
    WHERE FirstName = e.FirstName
    AND LastName = e.LastName
    WHERE Coursecompleted = '1'
    FOR XML PATH('')),1,1,'') AS CoursesCompleted
    from EStudentsprogress e
    where Coursecompleted = '1'
    Group by FirstName, LastName, CourseTitle, Noofmodules ;
    If not please provide some sample data and explain the output you want
    Please Mark This As Answer if it solved your issue
    Please Mark This As Helpful if it helps to solve your issue
    Visakh
    My MSDN Page
    My Personal Blog
    My Facebook Page
    I AM HAVING Incorrect syntax near the keyword 'WHERE'. 
    It was a typo
    try this
    select FirstName,
    LastName,
    CourseTitle,
    Noofmodules,
    count (Coursecompleted) as modulescompleted,
    STUFF((SELECT ',' + CourseTitle
    FROM EStudentsprogress
    WHERE FirstName = e.FirstName
    AND LastName = e.LastName
    AND Coursecompleted = '1'
    FOR XML PATH('')),1,1,'') AS CoursesCompleted
    from EStudentsprogress e
    where Coursecompleted = '1'
    Group by FirstName, LastName, CourseTitle, Noofmodules ;
    Please Mark This As Answer if it solved your issue
    Please Mark This As Helpful if it helps to solve your issue
    Visakh
    My MSDN Page
    My Personal Blog
    My Facebook Page
    its populating all the result for a particular customer, so i added another clause to  it and it worked
    select FirstName,
    LastName,
    CourseTitle,
    Noofmodules, 
    count (Coursecompleted) as modulescompleted,
    STUFF((SELECT ','  + CourseTitle
    FROM EStudentsprogress 
    WHERE FirstName = e.FirstName
    AND LastName = e.LastName
    AND Coursecompleted = '1'
    AND CourseTitle = e.CourseTitle
    FOR XML PATH('')),1,1,'') AS CoursesCompleted
    from EStudentsprogress e
    where Coursecompleted = '1'
    Group by FirstName, LastName, CourseTitle, Noofmodules ;
    but the result of the column is long , so i tried to used the course module, which is a column with numbers, and i tried modifying the query , but i had Error converting data type varchar to float.( i checked and saw that stuff is for concatinating
    strings) is there a way around it.
    i used 
    select FirstName,
    LastName,
    CourseModule,
    CourseTitle,
    Noofmodules, 
    count (Coursecompleted) as modulescompleted,
    STUFF((SELECT ','  + CourseModule
    FROM EStudentsprogress 
    WHERE FirstName = e.FirstName
    AND LastName = e.LastName
    AND Coursecompleted = '1'
    AND CourseTitle = e.CourseTitle
    FOR XML PATH('')),1,1,'') AS CoursesCompleted
    from EStudentsprogress e
    where Coursecompleted = '1'
    Group by FirstName, LastName,CourseModule, CourseTitle, Noofmodules ;

  • Join numeric with join numbers function

    Hi !  a small question from a guy that didnt use labview for a while !
    i need to use the join number function to join two DBL number A and B to form a new number A.B, just like the join numbers function
    in the example i would like the results after the join number function to be 1.5 
    however i understand that the function merge bytes/words together and the result is far from what i expect ....  any ways to 
    A and B are extracted from modbus READ register command and are unsigned 16 bit
    seems easy enough but i need a good refreshment on how those bits, bytes and numeric works together..   doh !
    thank for everyone involved, Kudos to all labview champions!
    Solved!
    Go to Solution.
    Attachments:
    join numbers.png ‏108 KB
    test comm.png ‏91 KB

    Hi yan,
    it seems you really need a refreshment on all those bits/bytes/numeric representations
    Typecasting floats (DBL) to U16 will probably never result in the desired value.
    Why do you convert your U16 modbus values to DBL anyway? Stick with U16 and you will have no problems using JOIN or any other bit-banging function...
    Best regards,
    GerdW
    CLAD, using 2009SP1 + LV2011SP1 + LV2014SP1 on WinXP+Win7+cRIO
    Kudos are welcome

  • How to define in different controls device and channels in a DAQmx function?

    Hi,
    I need to build a vi that permits the user to change the device of a DAQmx  acquisition system, although I don't want that the user modify the input channels. I`d like to know if it is possible to define in different controls device and channels.
    []´s
    Juliana

    Hello Juliana,
    What you would like to do is possible with some simple string manipulation.  First you will need a Device Name constant from the DAQmx >> Advanced >> DAQmx Constants & Property Nodes palette.  Right-click on the constant and turn it into a control.  Then, use a concatenate strings function to join the device name with the rest of the characters you need to define your input channels.  Wire the output of the concatenate strings VI to your DAQmx Create Channel VI.
    Let me know if you have any questions on this.
    Thanks,
    Laura

  • No more smooth/corner option when joining endpoints in CS5?

    OK, I've looked around for the answer. Where did the smooth/corner dialog box go in CS5? Yes, my points are aligned.
    Thanks

    There are two updates related to Join functionality in CS5.
    1. There is a new functionality to join two anchor points of same or different paths by using Cmd/Ctrl+J. You don't even need to select the anchor points - just select the path in full and press Cmd/Ctrl+J. The closest anchor points are detected and joined. A second press of Cmd/Ctrl+J would join the remaining ends. Example:
    To join the anchor points of your choice, just select those anchor points and press Cmd/Ctrl+J. Example:
    2. The earlier shortcut to join two overlapping anchor points is different in CS5. It used to be Cmd/Ctrl+J, but now it is Cmd/Ctrl+Shift+Opt/Alt+J. The method remains the same i.e. the two anchor point have to be overlapping and selected.
    Hope this helps.
    Neeraj

  • How to pass parameter into extract function (for XMLTYPE)

    I have a table PROBLEMXML with XMLTYPE field xml_column. In this column there are several deffinitions for the problem. There is no max amount of deffinitions and it can be no definition at all. I need to return all definitions for every problem as a string wirh definitions separated by ";".
    Query
    SELECT extract(prob.Def,'/Definitions/Definition[1]/@var') || ';'|| extract(prob.Def,'/Definitions/Definition[2]/@var')
    FROM PROBLEMXML j ,
    XMLTABLE (
    '/problem'
    PASSING j.xml_column
    COLUMNS probid VARCHAR (31) PATH '/problem/@id',
    Def XMLTYPE PATH '/problem/Definitions') prob
    where PROBLEM_ID =1;
    returns exactly what I want a;m.
    But
    declare
    my_var varchar2(2000) :=null;
    n1 number;
    n2 number;
    begin
    n1:=1;
    n2:=2;
    SELECT extract(prob.Def,'/Definitions/Definition[n1]/@var') || '|'|| extract(prob.Def,'/Definitions/Definition[n2]/@var') into my_var
    FROM ETL_PROBLEMXML_STG_T j ,
    XMLTABLE (
    '/problem'
    PASSING j.xml_column
    COLUMNS probid VARCHAR (31) PATH '/problem/@id',
    Def XMLTYPE PATH '/problem/Definitions') prob
    where PROBLEM_ID =1;
    dbms_output.put_line(my_var);
    end;
    returns NULL.
    Is there is a way to pass parameter into extract function?

    I need to return all definitions for every problem as a string wirh definitions separated by ";".In XQuery, there's the handy function "string-join" for that.
    For example :
    SQL> WITH etl_problemxml_stg_t AS (
      2   SELECT 1 problem_id,
      3  xmltype('<problem id="1">
      4   <Definitions>
      5    <Definition var="var1"></Definition>
      6    <Definition var="var2"></Definition>
      7    <Definition var="var3"></Definition>
      8   </Definitions>
      9  </problem>') xml_column
    10   FROM dual
    11  )
    12  SELECT j.problem_id,
    13         prob.probid,
    14         prob.def
    15  FROM etl_problemxml_stg_t j,
    16       XMLTable(
    17        'for $i in /problem
    18         return element r
    19         {
    20          $i/@id,
    21          element d { string-join($i/Definitions/Definition/@var, ";") }
    22         }'
    23        passing j.xml_column
    24        columns
    25         probid varchar2(30)  path '@id',
    26         def    varchar2(100) path 'd'
    27       ) prob
    28  ;
    PROBLEM_ID PROBID               DEF
             1 1                    var1;var2;var3

  • How to use object type collection in my function?

    Hi,
    I want to declare Object type collection with in my function like same a Record type collection. But it is saying error like below
    PLS-00540: object not supported in this context.
    Can anyone tell me how can i resolve this? I don't want to go with create object type functionality.
    Thanks

    Hi below is my full query.
    SELECT  czci.config_hdr_id,
            czci.config_rev_nbr,
            asoqla.quantity,
             (SELECT 
                    node_desc.LOCALIZED_STR
                 FROM   CZ_LOCALIZED_TEXTS node_desc,
                        CZ_PS_NODES ps_nodes,
                        CZ_CONFIG_ITEMS czci1
                WHERE   czci1.config_hdr_id = asoqld.config_header_id
                AND     czci1.config_rev_nbr = asoqld.config_revision_num
                AND    node_desc.INTL_TEXT_ID = ps_nodes.INTL_TEXT_ID
                AND     NVL(node_desc.LANGUAGE,userenv('LANG')) = userenv('LANG')
                AND     czci1.PS_NODE_ID = ps_nodes.PERSISTENT_NODE_ID
                 AND    ps_nodes.DEVL_PROJECT_ID = (SELECT MAX(DEVL_PROJECT_ID) FROM CZ_PS_NODES WHERE PERSISTENT_NODE_ID = czci.PS_NODE_ID)
                AND czci.PARENT_CONFIG_ITEM_ID IN (SELECT sub_sub.CONFIG_ITEM_ID FROM CZ_CONFIG_ITEMS sub_sub
                                                        WHERE sub_sub.CONFIG_HDR_ID = asoqld.config_header_id
                                                        AND sub_sub.CONFIG_REV_NBR = asoqld.config_revision_num
                                                        AND      sub_sub.PS_NODE_NAME = 'fittings')) fitting_material,
             (SELECT 
                    node_desc.LOCALIZED_STR
                 FROM   CZ_LOCALIZED_TEXTS node_desc,
                        CZ_PS_NODES ps_nodes,
                        CZ_CONFIG_ITEMS czci
                WHERE   czci.config_hdr_id = asoqld.config_header_id
                AND     czci.config_rev_nbr = asoqld.config_revision_num
                AND    node_desc.INTL_TEXT_ID = ps_nodes.INTL_TEXT_ID
                AND NVL(node_desc.LANGUAGE,userenv('LANG')) = userenv('LANG')
                AND     czci.PS_NODE_ID = ps_nodes.PERSISTENT_NODE_ID
                 AND    ps_nodes.DEVL_PROJECT_ID = (SELECT MAX(DEVL_PROJECT_ID) FROM CZ_PS_NODES WHERE PERSISTENT_NODE_ID = czci.PS_NODE_ID)
                AND czci.PARENT_CONFIG_ITEM_ID IN (SELECT sub_sub.CONFIG_ITEM_ID FROM CZ_CONFIG_ITEMS sub_sub
                                                        WHERE sub_sub.CONFIG_HDR_ID = czci.CONFIG_HDR_ID
                                                        AND sub_sub.CONFIG_REV_NBR = czci.CONFIG_REV_NBR
                                                        AND      sub_sub.PS_NODE_NAME = 'tubing')) tubing_material,
            NVL((SELECT czci.item_val
             FROM cz_config_items czci
             WHERE     czci.config_hdr_id = asoqld.config_header_id
             AND czci.config_rev_nbr = asoqld.config_revision_num
             AND czci.value_type_code <> 4
             AND czci.ps_node_name = 'control_circuit_name'),
             (SELECT 
                    node_desc.LOCALIZED_STR
                 FROM   CZ_LOCALIZED_TEXTS node_desc,
                        CZ_PS_NODES ps_nodes,
                        CZ_CONFIG_ITEMS czci
                WHERE   czci.config_hdr_id = asoqld.config_header_id
                AND     czci.config_rev_nbr = asoqld.config_revision_num
                AND    node_desc.INTL_TEXT_ID = ps_nodes.INTL_TEXT_ID
                AND NVL(node_desc.LANGUAGE,userenv('LANG')) = userenv('LANG')
                AND     czci.PS_NODE_ID = ps_nodes.PERSISTENT_NODE_ID
                 AND    ps_nodes.DEVL_PROJECT_ID = (SELECT MAX(DEVL_PROJECT_ID) FROM CZ_PS_NODES WHERE PERSISTENT_NODE_ID = czci.PS_NODE_ID)
                AND czci.PARENT_CONFIG_ITEM_ID IN (SELECT sub_sub.CONFIG_ITEM_ID FROM CZ_CONFIG_ITEMS sub_sub
                                                        WHERE sub_sub.CONFIG_HDR_ID = czci.CONFIG_HDR_ID
                                                        AND sub_sub.CONFIG_REV_NBR = czci.CONFIG_REV_NBR
                                                        AND      sub_sub.PS_NODE_NAME = 'pneumatic_schematics'))
             ) schematic_name
    FROM    aso_quote_lines_all asoqla,
            aso_quote_line_details asoqld,
            cz_config_items czci
    WHERE   asoqla.quote_header_id = 58455
    AND     asoqla.item_type_code = 'MDL'
    AND     asoqla.quote_line_id = asoqld.quote_line_id 
    AND     asoqld.config_header_id = czci.config_hdr_id
    AND     asoqld.config_revision_num = czci.config_rev_nbrBelow is my explain plan
    call     count       cpu    elapsed       disk      query    current        rows
    Parse        1      0.11       0.11          0          0          0           0
    Execute      2      0.01       0.01          0          0          0           0
    Fetch        3      0.06       0.06          0       3429          0          19
    total        6      0.18       0.18          0       3429          0          19That's what i am planning to write each select queries in a pipelined function then join all the functions. If i run one each query it is giving less query fetch
    Thanks

  • Join, the reverse of split?

    Hi,
    doing split on a string is easy in express... and you get an array as a result...
    but there doesn't seem to be a corresponding join where you can add an array of string with a specific string as separator.
    So, I should use concat... probably in combination with dolist
    but there doesn't seem to be a good join functionality, the join tjat I can call adds spaces and cant be varied it seems
    how would you recommend to emulate the normal join in xpress?

    Replying to my own post then....
    Got it to work, finally :-D
    given an array, derived from the users view and some properties on each account...
    pwsafeNames
    <List>
      <String>Lighthouse</String>
      <String>AD</String>
      <String>AD|2</String>
    </List>it builds a nice regular expression for my selectall checkbox :D
      <String>^resourceAccounts\\..+\\[(Lighthouse|AD|AD\\|2)]\\.selected$</String>with the following code...
    <concat>
      &lt;s>^resourceAccounts\\..+</s>
      <cond>
        <gt>
          <length>
            <ref>pwsafeNames</ref>
          </length>
          &lt;i>0</i>
        </gt>
        <block>
          <set name='fixed'>
            <dolist name='pwname'>
              <ref>pwsafeNames</ref>
              <cond>
                <contains>
                  <ref>pwname</ref>
                  &lt;s>|</s>
                </contains>
                <block>
                  <concat>
                    <get>
                      <split>
                        <ref>pwname</ref>
                        &lt;s>|</s>
                      </split>
                      &lt;i>0</i>
                    </get>
                    &lt;s>\\|</s>
                    <get>
                      <split>
                        <ref>pwname</ref>
                        &lt;s>|</s>
                      </split>
                      &lt;i>1</i>
                    </get>
                  </concat>
                </block>
                <ref>pwname</ref>
              </cond>
            </dolist>
          </set>
          <set name='pwarrsize'>
            <length>
              <ref>fixed</ref>
            </length>
          </set>
          <cond>
            <gt>
              <ref>pwarrsize</ref>
              &lt;i>0</i>
            </gt>
            <block>
              <set name='str'>
                <concat>
                  &lt;s>\\[(</s>
                  <get>
                    <ref>fixed</ref>
                    &lt;i>0</i>
                  </get>
                </concat>
              </set>
              <set name='counter'>
                &lt;i>1</i>
              </set>
              <while>
                <gt>
                  <ref>pwarrsize</ref>
                  <ref>counter</ref>
                </gt>
                <block>
                  <set name='str'>
                    <concat>
                      <ref>str</ref>
                      &lt;s>|</s>
                      <get>
                        <ref>fixed</ref>
                        <ref>counter</ref>
                      </get>
                    </concat>
                  </set>
                  <set name='counter'>
                    <add>
                      <ref>counter</ref>
                      &lt;i>1</i>
                    </add>
                  </set>
                </block>
              </while>
              <set name='str'>
                <concat>
                  <ref>str</ref>
                  &lt;s>)]</s>
                </concat>
              </set>
            </block>
            <set name='str'>
              <concat>
                &lt;s></s>
              </concat>
            </set>
          </cond>
          <ref>str</ref>
        </block>
      </cond>
      &lt;s>\\.selected$</s>
    </concat>To bad this forums code tag cant handle &lt;s> and &lt;i> tags, need to replace all &lt; with &amp;lt;
    Edited by: Dhurgan on Nov 13, 2012 11:09 AM

  • PipeLine Function Taking time to return Table record

    Hi,
    I want to use a function in join clause. so i go for pipelined function(using for loop to get record & 1 more loop to fetch in table type variable). i achieved what i required. but problem is it takes much time to fetch data. is there any other approach which returns table records without pipelined function.
    please suggest me a better approach as soon as possible.

    Hi,
    Thanks all for the quick response.
    I am using oracle 10g
    this is the table details & the entire function.
    Create object & table type to use in the function
    CREATE OR REPLACE TYPE SYSADM.STR_TYPE AS OBJECT(COLUMNVALUE VARCHAR2(8),FromNo Int,ToNo Int)
    CREATE OR REPLACE TYPE SYSADM.STR_ARRAY AS TABLE OF STR_TYPE
    table involved
    View : VesselType
    column : Code varchar2(5)
    Table : T065_SHIP
    column : SKIPS_KODE varchar2(4)
    CODE_SHIPTYPE varchar2(5)
    Table : SelsKap
    column : SELSKAPSKODE varchar2(4)
    Table : t041_shiptypeusers
    column : Code_ShipType varchar2(5)
    USERID varchar2(8)
    View : PositionBook
    column : VesselCode varchar2(8)
    VoyageNo integer
    Company varchar2(4)
    Table : T62_BRUKER_SELSKAP
    column : SELSKAPSKODE varchar2(4)
    BRUKER varchar2(8)
    Pipelined function
    CREATE OR REPLACE FUNCTION SYSADM.TF_ShiporShipTypeByUser
    In_UserName IN VARCHAR2,
    In_Type IN VARCHAR2,
    In_VesselCode IN VARCHAR2,
    In_CompanyHistory IN NUMBER DEFAULT 0
    RETURN str_array PIPELINED AS
    l_ShipTypeUser NUMBER(10,0);
    l_CompanyUser NUMBER(10,0);
    l_UseCompanyHistory NUMBER(1,0);
    l_Snicsacct NUMBER(1,0);
    BEGIN
    BEGIN
    SELECT shiptype_user,
    company_user
    INTO l_ShipTypeUser,
    l_CompanyUser
    FROM User_Segregation;
    EXCEPTION
    WHEN OTHERS THEN
    l_ShipTypeUser := NULL;
    l_CompanyUser := NULL;
    END;
    BEGIN
    SELECT 1 INTO l_Snicsacct
    FROM DUAL
    WHERE NOT EXISTS ( SELECT 1 FROM sn_user_cfg WHERE UserID='SNICS' and CfgID='ACCTSYS');
    EXCEPTION
    WHEN OTHERS THEN
    NULL;
    END;
    IF In_CompanyHistory = 1
    THEN
    BEGIN
    SELECT CfgData
    INTO l_UseCompanyHistory
    FROM SN_User_Cfg
    WHERE CfgID = 'USE COMPANY HISTORY'
    AND UserID = 'SNICS';
    EXCEPTION
    WHEN OTHERS THEN
    l_UseCompanyHistory := 0;
    END;
    END IF;
    IF In_UserName = 'SYSADM' OR (l_CompanyUser = 0 AND l_ShipTypeUser = 0)
    OR (l_CompanyUser = 1 and l_Snicsacct =1 ) or (In_CompanyHistory = 0 and l_CompanyUser = 1 and In_Type ='ShipType')
    OR (l_ShipTypeUser = 1 and In_Type = 'Company')
    THEN
    BEGIN
    IF In_Type = 'ShipType'
    THEN
    BEGIN
    FOR cur IN (SELECT Code ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM VesselType )
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    ELSIF In_Type = 'Ship'
    THEN
    BEGIN
    FOR cur IN (SELECT SKIPS_KODE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP
    WHERE SKIPS_KODE = NVL(In_VesselCode,SKIPS_KODE ))
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    ELSIF In_Type = 'Company'
    THEN
    BEGIN
    FOR cur IN (SELECT SELSKAPSKODE ShipCode
    , NULL VoyageFrom
    , NULL VoyageTo
    FROM SelsKap)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    END IF;
    END;
    ELSE
    IF In_Type = 'Ship'
    THEN
    BEGIN
    IF l_ShipTypeUser =1
    THEN
    BEGIN
    FOR cur IN (SELECT S.SKIPS_KODE ShipCode
    , 1 FromVoyage
    , 999999999 ToVoyage
    FROM T065_SHIP S
    JOIN t041_shiptypeusers U
    ON S.CODE_SHIPTYPE = U.Code_ShipType
    AND USERID = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    GROUP BY S.SKIPS_KODE)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.FromVoyage,cur.ToVoyage));
    END LOOP;
    RETURN;
    END;
    ELSIF l_CompanyUser = 1
    THEN
    BEGIN
    IF l_UseCompanyHistory = 1 AND In_CompanyHistory = 1
    THEN
    FOR cur IN (SELECT a.VesselCode ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    JOIN T62_BRUKER_SELSKAP b
    ON a.Company = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    UNION
    SELECT a.VesselCode ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.VesselCode,
    a.VoyageNo,
    a.VoyageNo)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    ELSE
    FOR cur IN (SELECT a.SKIPS_KODE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP a
    JOIN T62_BRUKER_SELSKAP b
    ON a.Company = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.SKIPS_KODE = NVL(In_VesselCode, a.SKIPS_KODE)
    AND NVL(l_UseCompanyHistory,0) = 0
    UNION
    SELECT a.SKIPS_KODE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.SKIPS_KODE = NVL(In_VesselCode, a.SKIPS_KODE)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.SKIPS_KODE)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END IF;
    END;
    END IF;
    END;
    ELSIF In_Type = 'ShipType'
    THEN
    IF l_ShipTypeUser = 1
    THEN
    BEGIN
    FOR cur IN (SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    JOIN t041_shiptypeusers U
    ON S.CODE_SHIPTYPE = U.Code_ShipType
    AND USERID = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    GROUP BY S.CODE_SHIPTYPE)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    ELSIF l_CompanyUser = 1
    THEN
    IF l_UseCompanyHistory = 1 AND In_CompanyHistory = 1
    THEN
    BEGIN
    FOR cur IN (SELECT a.VesselType ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    JOIN T62_BRUKER_SELSKAP b
    ON a.COMPANY = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.VesselCode = NVL(In_VesselCode,a.VesselCode)
    UNION
    SELECT a.VesselType ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.VesselType,
    a.VoyageNo,
    a.VoyageNo)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    ELSE
    BEGIN
    FOR cur IN (SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    JOIN T62_BRUKER_SELSKAP b
    ON S.company = b.SELSKAPSKODE
    AND B.BRUKER = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    AND NVL(l_UseCompanyHistory,0) = 0
    UNION
    SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON S.company = b.SELSKAPSKODE
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    AND b.SELSKAPSKODE IS NULL)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    END IF;
    END IF;
    ELSIF In_Type = 'Company'
    THEN
    BEGIN
    FOR cur IN (SELECT a.SELSKAPSKODE ShipCode
    , NULL VoyageFrom
    , NULL VoyageTo
    FROM Selskap a
    JOIN T62_BRUKER_SELSKAP b
    ON a.SELSKAPSKODE = b.SELSKAPSKODE
    WHERE b.BRUKER = In_UserName
    Union All
    Select a.SELSKAPSKODE ShipCode
    , NULL VoyageFrom
    , NULL VoyageTo
    From Selskap a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.SELSKAPSKODE = b.SELSKAPSKODE
    Where b.SELSKAPSKODE IS NULL
    GROUP BY a.SELSKAPSKODE)
    LOOP
    PIPE ROW(str_type(cur.ShipCode,cur.VoyageFrom,cur.VoyageTo));
    END LOOP;
    RETURN;
    END;
    END IF;
    END IF;
    END;
    select statement which i call the function it takes minimum 6 seconds to execute. It gives 8339 records
    WITH deftbl AS ( SELECT /*+ CACHE(deftbl) */
    /*+ result_cache */
    a.VesselCode,
    a.VoyageNo,
    CASE a.BallastLeg When 0
    THEN MIN(a.ArrivalDate)
    ELSE NVL(( SELECT MAX(DepartureDate)
    FROM PositionBook b
    WHERE b.VesselCode = a.VesselCode
    AND b.VoyageNo = (Select MAX(VoyageNo) From PositionBook c Where c.VesselCode = a.VesselCode and c.VoyageNo<a.VoyageNo)
    ),MIN(a.ArrivalDate))
    END AS StartOfVoyage,
    MAX(DepartureDate) EndOfVoyage
    FROM PositionBook a
    JOIN TABLE(*TF_ShiporShipTypeByUser*('BKA', 'Ship', NULL, 1)) D        /*Calling the function*/
    ON D.ColumnValue = a.VesselCode
    AND a.VoyageNo BETWEEN D.FromVoyageNo AND D.ToVoyageNo
    GROUP BY VesselCode,VoyageNo,a.BallastLeg )
    SELECT /*+ result_cache */
    ROW_NUMBER() OVER(PARTITION BY a.VesselCode ORDER BY a.VoyageNo DESC) as "Row"
    ,a.VesselCode
    ,v.Name AS VesselName
    ,a.VoyageNo
    ,c.StartOfVoyage AS FromPort
    ,c.EndOfVoyage AS ToPort
    /*,a.FROMPORT
    ,a.TOPORT*/
    , CASE
    WHEN ( SELECT PortName
    FROM PositionBook b
    WHERE b.VesselCode = a.VesselCode
    AND b.VoyageNo = a.VoyageNo
    AND SYSDATE BETWEEN ArrivalDate AND DepartureDate ) IS NOT NULL
    THEN ( SELECT FIRST_VALUE(PortName) OVER(PARTITION BY b.vesselcode,b.VoyageNo ORDER BY b.vesselcode,b.VoyageNo,b.ArrivalDate,b.secondarytime)
    FROM PositionBook b
    WHERE b.VesselCode = a.VesselCode
    AND b.VoyageNo = a.VoyageNo
    AND SYSDATE BETWEEN ArrivalDate AND DepartureDate
    AND ROWNUM=1
    WHEN SYSDATE BETWEEN c.StartOfVoyage AND c.EndOfVoyage
    THEN ( SELECT 'Steam From '||FIRST_VALUE(UPPER(PortName)) OVER(PARTITION BY b.vesselcode,b.VoyageNo ORDER BY b.vesselcode,b.VoyageNo,b.ArrivalDate desc,b.secondarytime desc)
    FROM POSITIONBOOK b
    WHERE b.VesselCode = a.VesselCode AND b.VoyageNo = a.VoyageNo
    AND b.ArrivalDate<SYSDATE
    AND ROWNUM=1
    WHEN (c.StartOfVoyage-SYSDATE)>0
    THEN 'Voyage Not Started'
    WHEN (c.EndOfVoyage-SYSDATE)<0
    THEN 'Voyage Completed'
    ELSE Null
    END "Location"
    ,( SELECT MIN(b.PortName) KEEP(DENSE_RANK FIRST ORDER BY b.ArrivalDate,b.secondarytime) OVER(PARTITION BY b.VesselCode,b.VoyageNo)
    FROM POSITIONBOOK b
    WHERE b.VesselCode = a.VesselCode AND b.VoyageNo = a.VoyageNo
    AND b.ArrivalDate>SYSDATE
    AND ROWNUM=1
    ) AS NextPort
    , ( SELECT MIN(b.ArrivalDate) KEEP(DENSE_RANK FIRST ORDER BY b.ArrivalDate,b.secondarytime) OVER(PARTITION BY b.VesselCode,b.VoyageNo)
    FROM POSITIONBOOK b
    where b.VesselCode = a.VesselCode AND b.VoyageNo = a.VoyageNo
    AND b.ArrivalDate>SYSDATE
    AND ROWNUM=1
    ) AS NextETA
    ,a.STATUS VoyageStatus
    ,a.Trade
    ,UFN_MyVoyConcatinate_Values('FIXNOTE', a.VesselCode, a.VoyageNo) FixNote
    ,UFN_MyVoyConcatinate_Values('CHARTERER', a.VesselCode, a.VoyageNo) Charterer
    ,CASE WHEN st.CurrentStatus=0
    THEN 1
    WHEN st.CurrentStatus=1
    THEN 0
    ELSE st.CurrentStatus
    END AS CurrentStatus
    FROM Positionbook a
    JOIN deftbl c
    ON a.VesselCode = c.VesselCode
    AND a.VoyageNo = c.VoyageNo
    JOIN Vessel v
    ON v.Code = c.VesselCode
    LEFT JOIN GTT_VOYAGESTATUS st
    ON st.VesselCode = c.Vesselcode
    AND st.VoyageNo = c.VoyageNo
    GROUP BY a.VesselCode
    , v.Name
    , a.VoyageNo
    , c.StartOfVoyage
    , c.EndOfVoyage
    /*, a.FROMPORT
    , a.TOPORT*/
    , a.Status
    , a.Trade
    , st.CurrentStatus;
    Note:
    i changed the function without pipelined also. but it doesnt show much difference
    non pipelined function
    CREATE OR REPLACE FUNCTION TF_ShiporShipTypeByUser_nonp
    In_UserName IN VARCHAR2,
    In_Type IN VARCHAR2,
    In_VesselCode IN VARCHAR2,
    In_CompanyHistory IN NUMBER DEFAULT 0
    RETURN str_array AS
    l_ShipTypeUser NUMBER(10,0);
    l_CompanyUser NUMBER(10,0);
    l_UseCompanyHistory NUMBER(1,0);
    l_Snicsacct NUMBER(1,0);
    l_str_array str_array:=str_array();
    BEGIN
    BEGIN
    SELECT shiptype_user,
    company_user
    INTO l_ShipTypeUser,
    l_CompanyUser
    FROM User_Segregation;
    EXCEPTION
    WHEN OTHERS THEN
    l_ShipTypeUser := NULL;
    l_CompanyUser := NULL;
    END;
    BEGIN
    SELECT 1 INTO l_Snicsacct
    FROM DUAL
    WHERE NOT EXISTS ( SELECT 1 FROM sn_user_cfg WHERE UserID='SNICS' and CfgID='ACCTSYS');
    EXCEPTION
    WHEN OTHERS THEN
    NULL;
    END;
    IF In_CompanyHistory = 1
    THEN
    BEGIN
    SELECT CfgData
    INTO l_UseCompanyHistory
    FROM SN_User_Cfg
    WHERE CfgID = 'USE COMPANY HISTORY'
    AND UserID = 'SNICS';
    EXCEPTION
    WHEN OTHERS THEN
    l_UseCompanyHistory := 0;
    END;
    END IF;
    IF In_UserName = 'SYSADM' OR (l_CompanyUser = 0 AND l_ShipTypeUser = 0)
    OR (l_CompanyUser = 1 and l_Snicsacct =1 ) or (In_CompanyHistory = 0 and l_CompanyUser = 1 and In_Type ='ShipType')
    OR (l_ShipTypeUser = 1 and In_Type = 'Company')
    THEN
    BEGIN
    IF In_Type = 'ShipType'
    THEN
    BEGIN
    SELECT STR_TYPE(Code,1,999999999)
    BULK COLLECT INTO l_str_array
    FROM VesselType;
    RETURN l_str_array;
    END;
    ELSIF In_Type = 'Ship'
    THEN
    BEGIN
    SELECT STR_TYPE(SKIPS_KODE,1,999999999)
    BULK COLLECT INTO l_str_array
    FROM T065_SHIP
    WHERE SKIPS_KODE = NVL(In_VesselCode,SKIPS_KODE);
    RETURN l_str_array;
    END;
    ELSIF In_Type = 'Company'
    THEN
    BEGIN
    SELECT STR_TYPE(SELSKAPSKODE,NULL,NULL)
    BULK COLLECT INTO l_str_array
    FROM SelsKap;
    RETURN l_str_array;
    END;
    END IF;
    END;
    ELSE
    IF In_Type = 'Ship'
    THEN
    BEGIN
    IF l_ShipTypeUser =1
    THEN
    BEGIN
    SELECT STR_TYPE(S.SKIPS_KODE,1,999999999)
    BULK COLLECT INTO l_str_array
    FROM T065_SHIP S
    JOIN t041_shiptypeusers U
    ON S.CODE_SHIPTYPE = U.Code_ShipType
    AND USERID = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    GROUP BY S.SKIPS_KODE;
    RETURN l_str_array;
    END;
    ELSIF l_CompanyUser = 1
    THEN
    BEGIN
    IF l_UseCompanyHistory = 1 AND In_CompanyHistory = 1
    THEN
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM ( SELECT a.VesselCode ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    JOIN T62_BRUKER_SELSKAP b
    ON a.Company = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    UNION
    SELECT a.VesselCode ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.VesselCode,
    a.VoyageNo,
    a.VoyageNo);
    RETURN l_str_array;
    ELSE
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM (SELECT a.SKIPS_KODE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP a
    JOIN T62_BRUKER_SELSKAP b
    ON a.Company = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.SKIPS_KODE = NVL(In_VesselCode, a.SKIPS_KODE)
    AND NVL(l_UseCompanyHistory,0) = 0
    UNION
    SELECT a.SKIPS_KODE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.SKIPS_KODE = NVL(In_VesselCode, a.SKIPS_KODE)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.SKIPS_KODE);
    RETURN l_str_array;
    END IF;
    END;
    END IF;
    END;
    ELSIF In_Type = 'ShipType'
    THEN
    IF l_ShipTypeUser = 1
    THEN
    BEGIN
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM (SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    JOIN t041_shiptypeusers U
    ON S.CODE_SHIPTYPE = U.Code_ShipType
    AND USERID = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    GROUP BY S.CODE_SHIPTYPE);
    RETURN l_str_array;
    END;
    ELSIF l_CompanyUser = 1
    THEN
    IF l_UseCompanyHistory = 1 AND In_CompanyHistory = 1
    THEN
    BEGIN
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM ( SELECT a.VesselType ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    JOIN T62_BRUKER_SELSKAP b
    ON a.COMPANY = b.SELSKAPSKODE
    AND b.BRUKER = In_UserName
    WHERE a.VesselCode = NVL(In_VesselCode,a.VesselCode)
    UNION
    SELECT a.VesselType ShipCode
    , a.VoyageNo VoyageFrom
    , a.VoyageNo VoyageTo
    FROM PositionBook a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.company = b.SELSKAPSKODE
    WHERE a.VesselCode = NVL(In_VesselCode, a.VesselCode)
    AND b.SELSKAPSKODE IS NULL
    GROUP BY a.VesselType,
    a.VoyageNo,
    a.VoyageNo);
    RETURN l_str_array;
    END;
    ELSE
    BEGIN
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM ( SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    JOIN T62_BRUKER_SELSKAP b
    ON S.company = b.SELSKAPSKODE
    AND B.BRUKER = In_UserName
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    AND NVL(l_UseCompanyHistory,0) = 0
    UNION
    SELECT S.CODE_SHIPTYPE ShipCode
    , 1 VoyageFrom
    , 999999999 VoyageTo
    FROM T065_SHIP S
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON S.company = b.SELSKAPSKODE
    WHERE S.SKIPS_KODE = NVL(In_VesselCode, S.SKIPS_KODE)
    AND b.SELSKAPSKODE IS NULL);
    RETURN l_str_array;
    END;
    END IF;
    END IF;
    ELSIF In_Type = 'Company'
    THEN
    BEGIN
    SELECT STR_TYPE(ShipCode,VoyageFrom,VoyageTo)
    BULK COLLECT INTO l_str_array
    FROM ( SELECT a.SELSKAPSKODE ShipCode
    , NULL VoyageFrom
    , NULL VoyageTo
    FROM Selskap a
    JOIN T62_BRUKER_SELSKAP b
    ON a.SELSKAPSKODE = b.SELSKAPSKODE
    WHERE b.BRUKER = In_UserName
    Union All
    Select a.SELSKAPSKODE ShipCode
    , NULL VoyageFrom
    , NULL VoyageTo
    From Selskap a
    LEFT JOIN T62_BRUKER_SELSKAP b
    ON a.SELSKAPSKODE = b.SELSKAPSKODE
    Where b.SELSKAPSKODE IS NULL
    GROUP BY a.SELSKAPSKODE);
    RETURN l_str_array;
    END;
    END IF;
    END IF;
    END;please kindly provide me your valuable suggestions
    Edited by: ganex27lin on Mar 16, 2011 1:54 AM

  • Performance ... normal selects and the same selects in functions

    Hi there,
    hope you guys can help me a little.
    We use a bunch of dictionary tables to map certain values to IDs. In the "real" data tables we save the IDs instead of the values themselves.
    Those tables are usually pretty small.
    Normally we would join these tables into our selects, such as this:
    select ...
    from data_table d,
    lookup_table l
    where d.l_id=l.id
    But we also got some functions we use to lookup these values to have simple selects:
    select ..., my_function(l_id)
    from data_table
    Or for reverse lookup:
    select ...
    from data_table
    where l_id=my_function(l_id)
    Do you know, if smaller selects capsuled in functions are more or less performant then simply joining these tables into the big selects?
    Sometimes we also use small statements on large tables (4.000.000 records) ... sometimes we use them in functions as well ...
    select bla
    from large_table
    where id=...
    Thanks for your hints,
    Steff

    How you did your tests?
    A short conclusion of test below:
    I've created 2 tables one base table and one lookup table.
    Then created function to get lookup value from lookup table.
    then run select to get all lookup values from base table using join and using function.
    Join needed 0.01 sec, function needed at least 2.08 secs.
    Then I've created an anonymous script to loop through all base values and get aproprite lookup values using function and using join and compared results using runstats.
    As a result join performed at more than 2 times faster and required more than 2 times less latches.
    and here is the listing
    SQL> create table lookup_table (
      2  lkp_id number not null,
      3  lkp_val varchar2(10) not null);
    Table created.
    Elapsed: 00:00:00.00
    SQL> alter table lookup_table add constraint lkp_pk primary key (lkp_id);
    Table altered.
    Elapsed: 00:00:00.00
    SQL>
    SQL> insert into lookup_table select rownum, substr(object_name, 1, 10) from dba_objects;
    42221 rows created.
    Elapsed: 00:00:00.05
    SQL> create or replace function get_lkp_value (in_id number) return varchar2
      2  is
      3    ret lookup_table.lkp_val%TYPE;
      4  begin
      5    select lkp_val into ret from lookup_table where lkp_id = in_id;
      6    return ret;
      7  end;
      8  /
    Function created.
    Elapsed: 00:00:00.01
    SQL> create table base_table (
      2  bas_id number not null,
      3  bas_lkp_id number not null,
      4  bas_data varchar2(1000) not null);
    Table created.
    Elapsed: 00:00:00.00
    SQL>
    SQL> insert into base_table select rownum, rownum, object_name
      2  from dba_objects where rownum <= 42221;
    42221 rows created.
    Elapsed: 00:00:00.05
    SQL> alter table base_table add constraint bas_pk primary key (bas_id);
    Table altered.
    Elapsed: 00:00:00.02
    SQL> alter table base_table add constraint bas_lkp_fk foreign key (bas_lkp_id)
      2  references lookup_table (lkp_id);
    Table altered.
    Elapsed: 00:00:00.01
    SQL> create index bas_lkp_idx on base_table (bas_lkp_id);
    Index created.
    Elapsed: 00:00:00.02
    SQL> exec dbms_stats.gather_table_stats(user, 'lookup_table');
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:00.01
    SQL> exec dbms_stats.gather_table_stats(user, 'base_table');
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:00.02
    SQL> select count(distinct lkp_val) from (
      2    select bas_id, bas_data, get_lkp_value(bas_lkp_id) lkp_val
      3    from base_table);
    COUNT(DISTINCTLKP_VAL)                                                         
                     13622                                                         
    Elapsed: 00:00:03.01
    SQL> /
    COUNT(DISTINCTLKP_VAL)                                                         
                     13622                                                         
    Elapsed: 00:00:02.08
    SQL> /
    COUNT(DISTINCTLKP_VAL)                                                         
                     13622                                                         
    Elapsed: 00:00:03.01
    SQL> select count(distinct lkp_val) from (
      2    select bas_id, bas_data, lkp_val
      3    from base_table, lookup_table
      4    where bas_lkp_id = lkp_id);
    COUNT(DISTINCTLKP_VAL)                                                         
                     13622                                                         
    Elapsed: 00:00:00.01
    SQL> /
    COUNT(DISTINCTLKP_VAL)                                                         
                     13622                                                         
    Elapsed: 00:00:00.01
    SQL> ed
    Wrote file afiedt.buf
      1  declare
      2    cursor c1 (in_id in number) is
      3    select bas_id, bas_data, lkp_val
      4    from base_table, lookup_table
      5    where bas_lkp_id = lkp_id
      6      and bas_id = in_id;
      7    val1 c1%ROWTYPE;
      8    cursor c2 (in_id in number) is
      9    select bas_id, bas_data, get_lkp_value(bas_lkp_id)
    10    from base_table
    11    where bas_id = in_id;
    12    val2 c2%ROWTYPE;
    13  begin
    14  runstats_pkg.rs_start;
    15  for i in 1..42220 loop
    16    open c1(i);
    17    fetch c1 into val1;
    18    close c1;
    19  end loop;
    20  runstats_pkg.rs_middle;
    21  for i in 1..42220 loop
    22    open c2(i);
    23    fetch c2 into val1;
    24    close c2;
    25  end loop;
    26  runstats_pkg.rs_stop;
    27* end;
    SQL> /
    Run1 ran in 390 hsecs                                                          
    Run2 ran in 910 hsecs                                                          
    run 1 ran in 42,86% of the time                                                
    Name                                  Run1        Run2        Diff             
    LATCH.kwqit: protect wakeup ti           0           1           1             
    LATCH.spilled msgs queues list           0           1           1             
    STAT...change write time                 0           1           1             
    LATCH.active checkpoint queue            1           3           2             
    LATCH.cache buffer handles              24          26           2             
    LATCH.process allocation                 0           2           2             
    STAT...cleanout - number of kt           3           5           2             
    STAT...consistent gets - exami     253,323     253,325           2             
    STAT...consistent gets             253,323     253,325           2             
    STAT...calls to kcmgcs                   3           5           2             
    STAT...active txn count during           3           5           2             
    LATCH.session timer                      1           3           2             
    LATCH.event group latch                  0           2           2             
    LATCH.channel handle pool latc           0           4           4             
    LATCH.transaction allocation             0           4           4             
    STAT...db block gets                   520         524           4             
    LATCH.list of block allocation           0           4           4             
    LATCH.process group creation             0           4           4             
    LATCH.dummy allocation                   0           4           4             
    LATCH.post/wait queue                   11          16           5             
    LATCH.Consistent RBA                    18          24           6             
    LATCH.mostly latch-free SCN             18          24           6             
    STAT...consistent changes              510         516           6             
    STAT...session logical reads       253,843     253,849           6             
    STAT...db block changes              1,020       1,026           6             
    LATCH.lgwr LWN SCN                      18          24           6             
    LATCH.channel operations paren           4          12           8             
    LATCH.user lock                          0           8           8             
    LATCH.simulator lru latch               13           2         -11             
    LATCH.sequence cache                    56          71          15             
    LATCH.redo writing                      59          82          23             
    LATCH.enqueues                          30          60          30             
    STAT...hot buffers moved to he          31           0         -31             
    LATCH.messages                         100         149          49             
    LATCH.cache buffers lru chain           91          33         -58             
    LATCH.session idle bit                 230         290          60             
    LATCH.SQL memory manager worka         136         223          87             
    STAT...free buffer requested            91           4         -87             
    STAT...shared hash latch upgra          87           0         -87             
    STAT...physical reads                   87           0         -87             
    LATCH.checkpoint queue latch            69         181         112             
    LATCH.session allocation                44         178         134             
    LATCH.redo allocation                  622         819         197             
    LATCH.undo global data                  61         263         202             
    LATCH.dml lock allocation               92         312         220             
    LATCH.row cache enqueue latch          356         580         224             
    LATCH.simulator hash latch          12,430      12,204        -226             
    LATCH.row cache objects                360         626         266             
    LATCH.enqueue hash chains              141         477         336             
    STAT...recursive cpu usage             259         596         337             
    STAT...Elapsed Time                    392         913         521             
    LATCH.library cache pin alloca         402       1,100         698             
    LATCH.cache buffers chains         257,991     260,038       2,047             
    STAT...calls to get snapshot s      42,221      84,441      42,220             
    STAT...execute count                42,221      84,441      42,220             
    STAT...recursive calls             126,662     168,882      42,220             
    STAT...session pga memory                0      65,536      65,536             
    LATCH.shared pool                   44,133     213,801     169,668             
    LATCH.library cache pin             86,473     256,185     169,712             
    LATCH.library cache                 87,511     342,530     255,019             
    Run1 latches total versus runs -- difference and pct                           
    Run1        Run2        Diff       Pct                                         
    491,506   1,090,381     598,875     45.08%                                     
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:13.06Gints Plivna
    http://www.gplivna.eu

Maybe you are looking for