UNION ALL destroyed performance

Strangely, we have 2 queries, which, when they run independently, running fast enough (2 seconds on the one hand, instantaneous to the other), but when they are concatenated into a UNION ALL query without the ORDER BY clause, it takes 45 seconds for him to run.

We tried to push the SQL code in a WITH clause and some other rewrites of the subquery, but no performance boost. Anyone seen this before?

version 10.1.0.4
-= Chuck

just a thought... I didn't really study plans explain it... (I find these very difficult to read, you do not have these SQL * Plus, you did?)

Tom Kyte mentioned somewhere (I find the thread later) you can use ROWNUM in two UNION ALL queries to "refine" the query. You might want to try it.
Because of the ROWNUM materialize you each request separately before combining the results.

Tags: Database

Similar Questions

  • Please help me with the Alternative of queries to replace the UNION ALL for two queries

    Hi all

    I have the query to retrieve assets employees salary count and in so far as below:

    Select ename, emp_no, sum (sal_till_2010), sum (sal_till_2014) of

    (select emp_no, ename, salary as sal_till_2010, 0 as sal_till_2014 of employee e1

    where effective_date < = 1 January 2010 ' and not exists (select 1 from e2 employee_deletion where e2.emp_no = e1.emp_no and e2.deletion_date < = January 1, 2010 "")

    UNION ALL

    Select ename, emp_no, 0 as sal_till_2010, salary as employee e1 sal_till_2014 - here is a dummy 0 salary until 2010 for the union of all the

    where effective_date < = 1 January 2014 "and not exists (select 1 from e2 employee_deletion where e2.emp_no = e1.emp_no and e2.deletion_date < = 1 January 2014") "

    Group of emp_no, ename;

    In this query, I get the total salary until 2010 and until 2014 in the employee table, dates are dynamically passed to the procedure, and this can change.

    But assume the date above and let me know the alternative of queries to improve performance because I use Union ALL and read the same table twice in the above query.

    Advice me with request to read the table once to fetch the same data as the above query.

    Thanks in advance.


    Hello

    Thanks for the display of the data of the sample; It's very useful!

    I think OP wants something like this:

    WITH cutoff_dates AS

    (

    SELECT TO_DATE (January 1, 2010 ', ' DD/MM/YYYY') AS cutoff_date, 2010 UNDER the label OF dual UNION ALL

    SELECT TO_DATE (1 January 2014 ', "DD/MM/YYYY"), double 2014

    )

    SELECT e.emp_no, e.ename

    , NVL (SUM (CASE WHEN c.label = 2010 THEN e.salary END), 0) AS sal_till_2010

    , NVL (SUM (CASE WHEN c.label = 2014 THEN e.salary END), 0) AS sal_till_2014

    E employee

    JOIN cutoff_dates c ON e.effective_date<=>

    WHERE DOES NOT EXIST)

    SELECT 1

    Of employee_deletion ed

    WHERE ed.emp_no = e.emp_no

    AND ed.deletion_date<=>

    )

    E.emp_no GROUP, e.ename

    ORDER BY e.emp_no

    ;

    Output of your sample data:

    EMP_NO ENAME SAL_TILL_2010 SAL_TILL_2014

    ---------- ------ ------------- -------------

    1 Mickey 450 0

    2 Donald 750 0

  • Concatenation and Union all

    Hello

    Oracle 9i performance Guide:

    ' Concatenation is useful for statements with different conditions, combined with a clause or.

    "If a query contains a WHERE clause with multiple conditions combined with GOLD operators, then the optimizer into a compound equivalent query that uses the UNION ALL operator set, if this makes the query to run more efficiently"

    Can someone tell me when the concatenation is better than the union and vice versa?
  • My UNION ALL is not enough work - help!

    Hi gurus.

    I hope one of you fine pro can sort this for me...

    I have a script which is currently if there is an employee number to double but NOT if there is a double number of NOR - what code should I include?
          SELECT DISTINCT per.person_id, per.business_group_id, per.last_name,
                          per.start_date, per.date_of_birth, per.email_address,
                          LPAD(per.employee_number,8,'0') employee_number,
                          per.first_name,
                          per.marital_status, per.middle_names, per.nationality,
                          per.national_identifier, per.sex, per.title,
                          padd.address_id, padd.primary_flag, padd.address_line1,
                          padd.address_line2, padd.address_line3,
                          padd.town_or_city, padd.postal_code,
                          padd.telephone_number_1, paas.assignment_id,
                          paas.assignment_number, paas.object_version_number,
                          paas.effective_start_date, paas.effective_end_date,
                          paas.job_id, paas.position_id, paas.location_id,
                          paas.organization_id, paas.assignment_type,
                          paas.supervisor_id, paas.default_code_comb_id,
                          paas.set_of_books_id, paas.period_of_service_id
                     FROM per_all_people_f per,
                          per_all_assignments_f paas,
                          per_addresses padd
                   
                      WHERE padd.person_id = per.person_id
                      AND paas.person_id(+) = per.person_id
                          AND TRIM (LEADING '0' FROM per.employee_number) = TRIM (LEADING '0' FROM :p_emp_number)
                          AND per.national_identifier <> :p_ni_number 
                          
                          
                            UNION ALL
              
              
                SELECT DISTINCT per.person_id, per.business_group_id, per.last_name,
                          per.start_date, per.date_of_birth, per.email_address,
                         LPAD(per.employee_number,8,'0') employee_number,
                          per.first_name,
                          per.marital_status, per.middle_names, per.nationality,
                          per.national_identifier, per.sex, per.title,
                          padd.address_id, padd.primary_flag, padd.address_line1,
                          padd.address_line2, padd.address_line3,
                          padd.town_or_city, padd.postal_code,
                          padd.telephone_number_1, paas.assignment_id,
                          paas.assignment_number, paas.object_version_number,
                          paas.effective_start_date, paas.effective_end_date,
                          paas.job_id, paas.position_id, paas.location_id,
                          paas.organization_id, paas.assignment_type,
                          paas.supervisor_id, paas.default_code_comb_id,
                          paas.set_of_books_id, paas.period_of_service_id
                     FROM per_all_people_f per,
                          per_all_assignments_f paas,
                          per_addresses padd
                   
                      WHERE padd.person_id = per.person_id
                      AND paas.person_id(+) = per.person_id
                          AND TRIM (LEADING '0' FROM per.employee_number) = TRIM (LEADING '0' FROM :p_emp_number)
                          AND per.national_identifier = :p_ni_number; 
    Thank you very much...

    Steven

    Hello

    JackyWhite wrote:
    .. the first section is scheduled to end with

     AND per.national_identifier <> p_ni_number 
    

    but for some reason any of this is not displayed on the screen.

    Do you mean it is supposed to be an inequality raise it after per.national_identifier and before p_ni_number ?
    This site do not display the operator <>, even inside code tags.
    When posting on this site, always use the other inequality operator! =. There is no difference in performance.
    >

    Its mainly because I need to put a RC in the script but could not because of the outer join if it was to be a UNION all operation This is why the half you get first a <> p_ni_number and the second you get an AND per.national_identifier = p_ni_number;...

    The restriction OR applies only to outer join conditions. In other words, you can not say

    WHERE   paas.person_id (+) = per.per.person_id
    OR      pass.fubar (+)     = per.fubar
    

    (You can do this by using the notation ANSI; just one of the many reasons we syntax ANSII).
    However, you can use OR other conditions; for example:

    WHERE   paas.person_id (+) = per.per.person_id
    AND     (   per.national_identifier != p_ni_number
            OR  per.national_identifier  = p_ni_number
            )
    

    which seems to be what you're trying to do. Moreover, the WHERE clause above is equivalent to

    WHERE   paas.person_id (+) = per.per.person_id
    AND     per.national_identifier IS NOT NULL
    AND     p_ni_number             IS NOT NULL
    

    Whenever you need help, post a few examples of data (CREATE TABLE and INSERT statements), and desired results based on these data to the format.
    Simplify as much as possible. For example, your actual query may involve 35 columns, but display only the columns used in the conditions, as well as maybe one more column per table. After that you have a solution for the simplest prioblem, adding that the other columns will be triviial.

  • Ask. UNION ALL on two tables of dummy data

    I had a bit of SQL that joined a dynamic no cross table with another table of dummy data.

    WITH tbl_job_data AS (SELECT 'N' argument1, 'Y' argument2, NULL argument3, 'Y' argument4 FROM DUAL)
       , tbl_params   AS (SELECT 1 col_seq, 'From Project Number' col_prompt, NULL col_data, NULL col_attrib FROM DUAL UNION ALL
                          SELECT 2 col_seq, 'To Project Number'   col_prompt, NULL col_data, NULL col_attrib FROM DUAL UNION ALL
                          SELECT 3 col_seq, 'Through Date'        col_prompt, NULL col_data, NULL col_attrib FROM DUAL UNION ALL
                          SELECT 4 col_seq, 'Summarize Cost'      col_prompt, NULL col_data, NULL col_attrib FROM DUAL)
        SELECT  NULL AS col_seq
              , NULL AS col_prompt
              , d.col_data
              , d.col_attrib
        FROM    tbl_job_data
        UNPIVOT INCLUDE NULLS
                    (col_attrib
                FOR  col_data  IN (argument1
                                 , argument2
                                 , argument3
                                 , argument4)
                    ) d
        UNION ALL
        SELECT  tbl_params.col_seq
              , tbl_params.col_prompt
              , tbl_params.col_data
              , tbl_params.col_attrib
        FROM    tbl_params;
    
    
       COL_SEQ COL_PROMPT          COL_DATA  COL_ATTRIB
    ---------- ------------------- --------- ----------
                                   ARGUMENT1 N       
                                   ARGUMENT2 Y       
                                   ARGUMENT3         
                                   ARGUMENT4 Y       
             1 From Project Number                   
             2 To Project Number                     
             3 Through Date                          
             4 Summarize Cost                       
    
    8 rows selected.
    

    Sorry to be very naïve and ignorant, but is be possible that I can get the output in 4 lines like that, by a union on 2 statements:

       COL_SEQ COL_PROMPT          COL_DATA  COL_ATTRIB
    ---------- ------------------- --------- ----------
             1 From Project Number ARGUMENT1 N       
             2 To Project Number   ARGUMENT2 Y       
             3 Through Date        ARGUMENT3         
             4 Summarize Cost      ARGUMENT4 Y       
    

    I guess not, because the 2 tables don't really have a lot in common with them, but I thought I'd ask.

    Thank you

    Previously, contributed to these requests by Frank Kulash

    https://community.Oracle.com/thread/3810284 et https://community.Oracle.com/message/13361473

    WITH

    tbl_job_data AS

    (SELECT "n" argument1, argument2 'Y', NULL argument3, 'Y' argument4)

    OF THE DOUBLE

    ),

    tbl_params AS

    (SELECT 1 col_seq, number 'of the project"col_prompt, col_data, NULL, NULL col_attrib OF DOUBLE UNION ALL)

    SELECT 2 col_seq, col_prompt 'for the project number", NULL, col_data, NULL col_attrib OF DOUBLE UNION ALL

    SELECT 3 col_seq, col_prompt 'Date', NULL, col_data, NULL col_attrib OF DOUBLE UNION ALL

    SELECT 4 col_seq, col_prompt "summarizes the cost", NULL, col_data, NULL FROM DUAL col_attrib

    )

    Select y.*, x.*

    from (SELECT on col_seq (d.col_data control) row_number()

    NULL AS col_prompt

    d.col_data

    d.col_attrib

    OF tbl_job_data

    MUST INCLUDE NULL VALUES

    (col_attrib

    FOR col_data IN (argument1

    argument2

    argument3

    argument4)

    ) d

    ) x,.

    (SELECT tbl_params.col_seq

    tbl_params.col_prompt

    tbl_params.col_data

    tbl_params.col_attrib

    OF tbl_params

    ) y

    where x.col_seq = y.col_seq

    COL_SEQ COL_PROMPT COL_DATA COL_ATTRIB COL_SEQ COL_PROMPT COL_DATA COL_ATTRIB
    1 Project number - - 1 - ARGUMENT1 N
    2 For the project number - - 2 - ARGUMENT2 THERE
    3 By Date - - 3 - ARGUMENT3 -
    4 Summarize the cost - - 4 - ARGUMENT4 THERE

    Concerning

    Etbin

  • How to filter records in a UNION ALL query

    Hi all

    I have only one requirement to filter records in a query UNION all. If we do not all matching records to one of the union, all question them.

    create table test_1(n1 number,n2 number,n3 number)
    
    insert into test_1 values(1,2,3);
    insert into test_1 values(11,22,33);
    insert into test_1 values(55,66,77);
    
    Case-1 :
    
    SELECT N1,N2,N3
    FROM TEST_1
    WHERE N2=2
    UNION ALL
    SELECT N1,N2,N3
    FROM TEST_1
    WHERE N3=3
    
    Output is : This is desired output(so we are good)
    
    1,2,3
    1,2,3
    
    Case 2 :
    
    SELECT N1,N2,N3
    FROM TEST_1
    WHERE N2=22
    UNION ALL
    SELECT N1,N2,N3
    FROM TEST_1
    WHERE N3=44
    
    Output : (Here is the problem: If we don't have matching records for anyone union all query we don't want any records)
    
    Output is coming : 11,22,33
    
    Out put : No Records (We want this output.)
    

    I hope I have given the clear example of my requirement.

    Thank you.

    with

    test_1 as

    (select 1 n1, n2 2, n3 3 of all the double union)

    Select 11,22,33 from all the double union

    Select double 55,66,77

    )

    Select the n1, n2, n3

    from (select n1, n2, n3

    of test_1

    where n2 =: n2

    Union of all the

    Select the n1, n2, n3

    of test_1

    where = n3: n3

    )

    where exists (select null from test_1 where n2 =: n2)

    and it exists (select null from test_1 where = n3: n3)

    Concerning

    Etbin

  • Why UNION ALL allows no column names only when a literal is used and there is at least 3 parts of the query?

    An artificial union all:

    SQL> SELECT Dummy FROM Dual ORDER BY Dummy;
    
    D
    -
    X
    
    SQL> SELECT Dummy FROM Dual UNION ALL SELECT Dummy FROM Dual ORDER BY Dummy;
    
    D
    -
    X
    X
    
    SQL> SELECT Dummy FROM Dual UNION ALL SELECT Dummy FROM Dual UNION ALL SELECT Dummy FROM Dual ORDER BY Dummy;
    
    D
    -
    X
    X
    X
    
    
    

    It literally changes it:

    SQL> SELECT NULL A FROM Dual ORDER BY A;
    
    A
    -
    
    
    SQL> SELECT NULL A FROM Dual UNION ALL SELECT NULL FROM Dual ORDER BY A;
    
    A
    -
    
    
    
    SQL> SELECT NULL A FROM Dual UNION ALL SELECT NULL FROM Dual UNION ALL SELECT NULL FROM Dual ORDER BY A;
    SELECT NULL A FROM Dual UNION ALL SELECT NULL FROM Dual UNION ALL SELECT NULL FROM Dual ORDER BY A
                                                                                                     *
    ERROR at line 1:
    ORA-00904: "A": invalid identifier
    
    
    SQL> SELECT NULL A FROM Dual UNION ALL SELECT NULL FROM Dual UNION ALL SELECT NULL FROM Dual ORDER BY 1;
    
    A
    -
    
    
    
    
    

    Why 3 is the magic number?

    My friend, this is what I would call a "bug".

    However, my opinion doesn't matter, because I do not work for Oracle

    You opened a SR with Oracle?

  • Union all with addistional field

    Hello

    Maybe this is a stupid question.

    I have two tables with 22 columns.

    Another table with 23 columns

    I want to combine these two tables using union all.

    In the first picture, I want back "NA" as the last field.

    In the second table, last column is varchar2.

    Instead of every column one by one and if I use select * in two queries and add "NA" to one?

    I want the union two queries can order and use it with the clause to retrieve values based on conditions somany.

    So I have to specify the names of column three times.

    I use oracle 10g

    Hello Krishna,

    Try

    select t1.*, 'NA' as  from table1 t1
    union
    select t2.* from table2 t2;
    

    concerning

    Kay

  • What better union all or create a separate slider

    Hi gurus

    I wonder if someone can help out me of this union is a good option, or create a separate slider for each union all is a good option. Which is preferable? Thanks in advance

    Concerning

    Shu

    You can use Union all instead of opening cursor much time to record the line and your code in the treatment of the sliders, exceptions.

    So it would be better to consider all the data at once and even within a single processing loop.

    Kind regards

    Prashant da Silva

  • UNION and UNION ALL giving multiple result sets even if INTERSECT does not lines.

    Hello

    I have a set of two queries. I used the UNION to join the result set. When I used UNION ALL, I get a different result set.

    BT when I use INTERSECT, I m not getting all the lines.

    SO, which I guess is, as operation INTERSECT isn't Govind all the lines, then the UNION and UNION ALL of the result sets must be simliar.

    But I m getting different result sets.

    Please guide me.

    Thank you.

    Hello

    UNION returns separate lines; UNION ALL returns all rows that produce queries.

    INTERSECT has nothing to do with it.  You can have the lines in a single query.  For example

    Job SELECTION

    FROM scott.emp

    UNION - ALL THE

    SELECT 'FUBAR '.

    DOUBLE;

    In this example, there is no overlap between the 2 queries (INTERSECT would have 0 rows).

    UNION produces 6 lines, because the query at the top of the page produces 5 distinct lines (of 14 total ranks) and the background query 1.

    UNION ALL product lines 15: 14 of the request from top and 1 of the request from the lower part.

    I hope that answers your question.

    If not, post a test script (if necessary) and complete, including some UNION, UNION ALL queries INTERSECT.  Post of the CREATE TABLE and INSERT statements for all tables using those queries (with the exception of the commonly available rtables, such as those of the scott schema) and a specific question, such as "the UNION query all product...» I expect the UNION query to produce... because... but instead, it produces... Why is this?  It seems contractict... manual which says that... ».

  • Concat Union all 3 rows

    Hi all

    Please I need help with th following question:

    WITH some_data LIKE)

    SELECT "CNDMNL75P65L736C" FC, "cp" cr, 0 as I1, 1 as I2, I3 OF double 0

    UNION ALL

    SELECT "PNZGCM74M24L736C", "cp" cr, 5, 0, 0 DOUBLE

    UNION ALL

    SELECT "," cp, '1', 675,0, 0 DOUBLE cr

    UNION ALL

    SELECT ", '027113850273' cp," cr, 0, 32, double 0

    UNION ALL

    SELECT ", '12298850273' cp," cr, 2, 0, 0 DOUBLE

    UNION ALL

    SELECT ", '35798850273' cp," cr, 0, 12, double 0

    UNION ALL

    SELECT ", '627771888273' cp," cr, 10, 2, 0 DOUBLE

    UNION ALL

    SELECT "XDZGCM74M22L736C", "cp" cr, 15, 0, 10 DOUBLE

    )

    Select * from some_data;

    FCCPCRI1 I2 I3
    CNDMNL75P65L736C0 1 0
    PNZGCM74M24L736C5 0 0
    1675 0 0
    0271138502730 32 0
    122988502732 0 0
    357988502730 12 0
    62777188827310 2 0
    XDZGCM74M22L736C15 0 10

    How can I get a something as; (Only) one record for every 3 rows, like this

    CNDMNL75P65L736C            0    1    0PNZGCM74M24L736C            5    0    0        1    675    0    0 (first 3 rows)
         027113850273        0    32  0    12298850273        2    0    0    35798850273        0    12    0      (next 3 rows, ) 
         627771888273        10    2   0 XDZGCM74M22L736C            15    0    10                         (and so on ) 
    

    Thanks in advance

    For the 11g version:

    WITH some_data AS (
      SELECT 'CNDMNL75P65L736C' cf,'' cp ,'' cr, 0 as I1, 1 as I2, 0 as I3 FROM dual
      UNION ALL
      SELECT 'PNZGCM74M24L736C' ,'' cp ,'' cr, 5, 0, 0 FROM dual
      UNION ALL
      SELECT '' , '' cp ,'1' cr, 675,0, 0 FROM dual
      UNION ALL
      SELECT '' , '027113850273' cp ,'' cr, 0 ,32, 0 FROM dual
      UNION ALL
      SELECT '' , '12298850273' cp ,'' cr, 2, 0 ,0 FROM dual
      UNION ALL
      SELECT '' , '35798850273' cp ,'' cr, 0, 12 ,0 FROM dual
      UNION ALL
      SELECT '' , '627771888273' cp ,'' cr, 10, 2 ,0 FROM dual
      UNION ALL
      SELECT 'XDZGCM74M22L736C' ,'' cp ,'' cr, 15, 0, 10 FROM dual
    )
    select * from (
    select a.*, mod(rownum-1,3)+1 rn, ceil(rownum/3) grp from some_data a
    )
    pivot(max(cf) cf, max(cp) cp, max(cr) cr, max(i1) i1, max(i2) i2, max(i3) i3
    for rn in (1 a,2 b,3 c));
    
    GRP A_CF A_CP A_CR A_I1 A_I2 A_I3 B_CF B_CP B_CR B_I1 B_I2 B_I3 C_CF C_CP C_CR C_I1 C_I2 C_I3
    1 CNDMNL75P65L736C 0 1 0 PNZGCM74M24L736C 5 0 0 1 675 0 0
    2 027113850273 0 32 0 12298850273 2 0 0 35798850273 0 12 0
    3 627771888273 10 2 0 XDZGCM74M22L736C 15 0 10

    For the 12 c version:

    WITH some_data AS (
      SELECT 'CNDMNL75P65L736C' cf,'' cp ,'' cr, 0 as I1, 1 as I2, 0 as I3 FROM dual
      UNION ALL
      SELECT 'PNZGCM74M24L736C' ,'' cp ,'' cr, 5, 0, 0 FROM dual
      UNION ALL
      SELECT '' , '' cp ,'1' cr, 675,0, 0 FROM dual
      UNION ALL
      SELECT '' , '027113850273' cp ,'' cr, 0 ,32, 0 FROM dual
      UNION ALL
      SELECT '' , '12298850273' cp ,'' cr, 2, 0 ,0 FROM dual
      UNION ALL
      SELECT '' , '35798850273' cp ,'' cr, 0, 12 ,0 FROM dual
      UNION ALL
      SELECT '' , '627771888273' cp ,'' cr, 10, 2 ,0 FROM dual
      UNION ALL
      SELECT 'XDZGCM74M22L736C' ,'' cp ,'' cr, 15, 0, 10 FROM dual
    )
    select * from some_data
    match_recognize(
      measures a.cf acf, a.cp acp, a.cr acr, a.i1 ai1, a.i2 ai2, a.i3 ai3,
               b.cf bcf, b.cp bcp, b.cr bcr, b.i1 bi1, b.i2 bi2, b.i3 bi3,
               c.cf ccf, c.cp ccp, c.cr ccr, c.i1 ci1, c.i2 ci2, c.i3 ci3
      pattern (a b{0,1} c{0,1})
      define a as 1=1, b as 1=1, c as 1=1
    );
    
    ACF ACP ACR AI1 AI2 AI3 BCF BCP BCR BI1 BI2 BI3 CCF CCP CCR CI1 CI2 CI3
    CNDMNL75P65L736C 0 1 0 PNZGCM74M24L736C 5 0 0 1 675 0 0
    027113850273 0 32 0 12298850273 2 0 0 35798850273 0 12 0
    627771888273 10 2 0 XDZGCM74M22L736C 15 0 10
  • Union all too slow for my query any alternative?

    Hello

    The following query prints the desired results. What I'm trying to do is to add to my query below is to also retrieve information from different dates (for example 01.01.2012 - 30.4.2012), more information below, but with 0 amounts. The only solution I found is to duplicate the query to a union and entry dates you want below. The problem is that, then the query is too slow.
    Any other recommendations are welcome
    SELECT s.trans_datetime,s.alloc_ref,s.accnt_code,s.treference,s.DESCRIPTN,sum(s.amount*(-1)) as amount,s.conv_code,sum(s.other_amt*(-1)) as other_amt,s.anal_t1,ss.descr,
    o.NTN_DESCR as flag,z.name as vessel_name
    FROM  accounts s, customers ss,vessel a,nation o, analysis  z,
    customers_anl_cat  z1
    where s.trans_datetime BETWEEN to_date('01.01.2013','DD.MM.YYYY') AND to_date('30.04.2013','DD.MM.YYYY')
    AND s.accnt_code=z1.acnt_code
    AND z1.anl_cat_id=17
    AND ss.ACNT_TYPE=2
    AND s.accnt_code=ss.acnt_code
    AND o.NTN_CODE=a.flg_code
    AND z.anl_code=s.anal_t1
    GROUP BY s.trans_datetime,s.alloc_ref,s.accnt_code,s.treference,s.DESCRIPTN,s.conv_code,s.anal_t1,ss.descr
    ,o.NTN_DESCR,z.name,z1.anl_code
    Thanks in advance

    794018 wrote:
    Thank you very much for your answers.

    Unfortunately, the lines of the new date in the amount and need to convert to 0 or null values

    OK... What is not eligible for a situation to replicate the query to use UNION all clause You can simply do more in select:

    Select  column_list1... column_listN,
    case when s.trans_datetime BETWEEN to_date('01.01.2013','DD.MM.YYYY') AND to_date('30.04.2013','DD.MM.YYYY') then s.amount
           when s.trans_datetime BETWEEN to_date('01.01.2012','DD.MM.YYYY') AND to_date('30.04.2012','DD.MM.YYYY') then 0
    end amount
    from table_names
    where (s.trans_datetime BETWEEN to_date('01.01.2013','DD.MM.YYYY') AND to_date('30.04.2013','DD.MM.YYYY') or s.trans_datetime BETWEEN to_date('01.01.2012','DD.MM.YYYY') AND to_date('30.04.2012','DD.MM.YYYY'))
    Other conditions Follow
    
  • Poblem with union/union all giving ORA-22950

    I use a select statement with the xmlelement to create an xml file.

    There the various unions end in 5, but I always bring a line through.

    I do like that as then I can use this as a cursor in my plsql without having to create lots of cursors when I only need to use a.
    That is to say.
    SELECT  xmlelement("QUOTATION",xmlagg(xmlelement(Quotation,
                          xmlelement(CUSTOMERNAME, customername),
                          xmlelement(QUOTE,quoteid )))xmlfile
    From cust, quote
    where custid=quotecustid
    and ptype = 'Q'
    UNION
    SELECT  xmlelement("SALES",xmlagg(xmlelement(SALES,
                          xmlelement(CUSTOMERNAME, customername),
                          xmlelement(QUOTE,salesid )))xmlfile
    From cust, sales
    where custid=salescustid
    and ptype = 'S'
    Then, I use a cursor to execute it in a ftp file folder I selected passing ptype as a parameter.

    If I use the union I get ORA-22950 - I have seen other people use UNION all around it.
    If I use union all I'll get a value for the SALE of any line that is

    Any ideas how I can get around this as do not want to continue to create cursors

    The use of different sliders is always the best approach IMO.
    All things considered, it should be more effective than that appearing more "smart" one.

    And there is no need to be explicit cursors, it could just be SELECT INTOs wrapped in a PL/SQL CASE statement, with the appropriate exception handler (if necessary).

    Anyway, if you want to stick with the single-cursor method, there are different ways to do this:

    (1) adding a column selector:

    SELECT xmlfile
    FROM (
      SELECT 'Q' as selector
           , xmlelement("QUOTATION",xmlagg(xmlelement(Quotation,
                      xmlelement(CUSTOMERNAME, customername),
                      xmlelement(QUOTE,quoteid )))xmlfile
      From cust, quote
      where custid=quotecustid
      and ptype = :1
      UNION ALL
      SELECT 'S'
           , xmlelement("SALES",xmlagg(xmlelement(SALES,
                      xmlelement(CUSTOMERNAME, customername),
                      xmlelement(QUOTE,salesid )))xmlfile
      From cust, sales
      where custid=salescustid
      and ptype = :1
    )
    WHERE selector = :1
    ;
    

    (2) adding a GROUP BY clause, so that XMLAgg returns nothing if no row is selected:

    SELECT xmlelement("QUOTATION",xmlagg(xmlelement(Quotation,
                    xmlelement(CUSTOMERNAME, customername),
                    xmlelement(QUOTE,quoteid )))xmlfile
    From cust, quote
    where custid=quotecustid
    and ptype = :1
    GROUP BY null
    UNION ALL
    SELECT xmlelement("SALES",xmlagg(xmlelement(SALES,
                    xmlelement(CUSTOMERNAME, customername),
                    xmlelement(QUOTE,salesid )))xmlfile
    From cust, sales
    where custid=salescustid
    and ptype = :1
    GROUP BY null
    ;
    

    (3) subqueries:

    SELECT case :1
            when 'Q' then ( SELECT ... )
            when 'S' then ( SELECT ... )
          end as xmlfile
    FROM dual
    ;
    
  • UNION ALL GROUP THEN SQL - is a better way

    Hi gurus of SQL,.

    Just try my luck to see if there is a better way to write the following SQL code. I don't know if the UNION ALL + GROUP BY is the best way. Is it better to use a FULL OUTER JOIN instead?

    Thanks for your time.

    See you soon
    Ligon
    SELECT 
       x.task_id,
       x.task_name,
       max(x.actual_effort)  actual_effort,
       max(x.date_completed) date_completed,
       max(x.status)         status
     FROM
     (         
          SELECT 
            t.task_id, 
            t.task_name,
            NULL actual_effort,
            NULL date_completed,
            NULL status
          FROM tt_tbl_tasks t, tt_tbl_emps e, tt_tbl_references r
          WHERE /*t.task_status = 'Y'
          AND*/ t.task_start_dt <= menu_util.get_date('15/02/2010',menu_util.df)
          AND NVL(t.task_end_dt,SYSDATE+9999) >= menu_util.get_date('15/02/2010',menu_util.df)
          AND e.emp_id = 'MEARS_MP'
          AND t.task_id = e.task_id
          AND r.ref_type = 'FREQUENCY'
          AND t.task_frequency = r.ref_id
          AND is_event_ready
              (p_start_dt => t.task_start_dt,
               p_end_dt   => t.task_end_dt,
               p_check_dt => menu_util.get_date('15/02/2010',menu_util.df),
               p_freq     => to_number(r.ref_name)) = 'Y'
         
         UNION ALL
         
         SELECT 
            t.task_id,
            t.task_name,
            ev.actual_effort,
            ev.date_completed,
            ev.status
          FROM tt_tbl_tasks t, tt_tbl_emps e, tt_tbl_events ev
          WHERE ev.date_completed = menu_util.get_date('15/02/2010',menu_util.df)
          AND t.task_id = ev.task_id
          AND e.emp_id = 'MEARS_MP'
          AND t.task_id = e.task_id
      )x
      GROUP BY  x.task_id,x.task_name
    ... and here's the plan
    Plan
    SELECT STATEMENT  ALL_ROWSCost: 11  Bytes: 178  Cardinality: 2                                          
         18 HASH GROUP BY  Cost: 11  Bytes: 178  Cardinality: 2                                     
              17 VIEW TTDB. Cost: 10  Bytes: 178  Cardinality: 2                                
                   16 UNION-ALL                           
                        8 NESTED LOOPS                      
                             6 NESTED LOOPS  Cost: 5  Bytes: 88  Cardinality: 1                 
                                  4 NESTED LOOPS  Cost: 4  Bytes: 65  Cardinality: 1            
                                       2 TABLE ACCESS BY INDEX ROWID TABLE TTDB.TT_TBL_TASKS Cost: 4  Bytes: 52  Cardinality: 1       
                                            1 INDEX RANGE SCAN INDEX TTDB.TT_TBL_TASKS_IDX_START_DT Cost: 2  Cardinality: 5  
                                       3 INDEX UNIQUE SCAN INDEX (UNIQUE) TTDB.TT_TBL_EMPS_PK Cost: 0  Bytes: 13  Cardinality: 1       
                                  5 INDEX UNIQUE SCAN INDEX (UNIQUE) TTDB.TT_TBL_REFERENCES_PK Cost: 0  Cardinality: 1            
                             7 TABLE ACCESS BY INDEX ROWID TABLE TTDB.TT_TBL_REFERENCES Cost: 1  Bytes: 23  Cardinality: 1                 
                        15 NESTED LOOPS  Cost: 5  Bytes: 64  Cardinality: 1                      
                             13 NESTED LOOPS  Cost: 5  Bytes: 102  Cardinality: 2                 
                                  10 TABLE ACCESS BY INDEX ROWID TABLE TTDB.TT_TBL_EVENTS Cost: 3  Bytes: 36  Cardinality: 2            
                                       9 INDEX RANGE SCAN INDEX TTDB.TT_TBL_EVENTS_IDX_DT_COMPLETED Cost: 1  Cardinality: 2       
                                  12 TABLE ACCESS BY INDEX ROWID TABLE TTDB.TT_TBL_TASKS Cost: 1  Bytes: 33  Cardinality: 1            
                                       11 INDEX UNIQUE SCAN INDEX (UNIQUE) TTDB.TT_TBL_TASKS_PK Cost: 0  Cardinality: 1       
                             14 INDEX UNIQUE SCAN INDEX (UNIQUE) TTDB.TT_TBL_EMPS_PK Cost: 0  Bytes: 13  Cardinality: 1                 

    Something like that I guess.

    select t.Task_ID
          ,t.Task_Name
          ,p.Actual_Effort
          ,p.Date_Completed
          ,p.Status
    from
        (
          select
                  t.Task_ID   as Task_ID
                 ,t.Task_Name as Task_Name
          from
                  tt_tbl_Tasks      t
                 ,tt_tbl_Emps       e
                 ,tt_tbl_References r
          where
                  t.Task_Start_Dt                   <= Menu_Util.Get_Date('15/02/2010',Menu_Util.Df)
          and     nvl(t.Task_End_Dt,sysdate + 9999) >= Menu_Util.Get_Date('15/02/2010',Menu_Util.Df)
          and     e.Emp_ID                          = 'MEARS_MP'
          and     t.Task_ID                         = e.Task_ID
          and     r.Ref_Type                        = 'FREQUENCY'
          and     t.Task_Frequency                  = r.Ref_ID
          and     is_Event_Ready
                 (p_Start_Dt => t.Task_Start_Dt,
                  p_End_Dt   => t.Task_End_Dt,
                  p_Check_Dt => Menu_Util.Get_Date('15/02/2010',Menu_Util.Df),
                  p_Freq     => to_number(r.Ref_Name)) = 'Y'
        ) t
    left join
          (
            select Task_ID
                 ,Task_Name
                 ,Actual_Effort
                 ,Date_Completed
                 ,Status
            from
                (
                 select
                    t.Task_ID           as Task_ID
                   ,t.Task_Name         as Task_Name
                   ,ev.Actual_Effort    as Actual_Effort
                   ,ev.Date_Completed   as Date_Completed
                   ,ev.Status           as Status
                   ,row_number() over  (partition by t.Task_ID, t.Task_Name
                                        order by ev.Actual_Effort   desc
                                                ,ev.Date_Completed  desc
                                                ,ev.Status          desc) rn
                  from    tt_tbl_Tasks      t
                         ,tt_tbl_Emps       e
                         ,tt_tbl_Events     ev
                  where
                          ev.Date_Completed = Menu_Util.Get_Date('15/02/2010', Menu_Util.Df)
                  and     t.Task_ID         = ev.Task_ID
                  and     e.Emp_ID          = 'MEARS_MP'
                  and     t.Task_ID         = e.Task_ID
                )
            where rn = 1
          ) p
    on  t.Task_ID   = p.Task_ID
    and t.Task_Name = p.Task_Name 
    

    The join type and if you filter by null will determine what your require, then its up to you to experiment.

  • UNION ALL in COLLECTION in BULK

    My code is like this:
    SELECT COL_NAME, COUNT BULK COLLECT INTO v_collections FROM
    (
    SELECT 'PROD_NAME' COL_NAME, COUNT(*) COUNT FROM TEST_TABLE
    WHERE LENGTH(PROD_NAME)>50  
    UNION ALL
    SELECT 'PROD_DESC' COL_NAME, COUNT(*) COUNT FROM TEST_TABLE
    WHERE PROD_DESC IS NULL
    .
    .
    .
    ..10 MORE UNION ALL
    );
    {code}
    
    --does it lead to one context switch or multiple one for each select in the union all
    --I do want to capture # of errors for each column 
    --although the code runs very fast, still I am worried that it may not be a good coding practice.
    --is there any better way to do this?
    --TEST_TABLE has 1 million records
    
    Thanks,
    RN                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

    >
    -causes change of context or more for each selection in the union all the
    >
    A single switch since the entire SQL (i.e. all queries combined set) is sent.
    >
    is there a better way to do it?
    >
    It depends on. What you do with the data you are interviewing?
    The best way is to use SQL instead of PL/SQL whenever possible. But since we do not know what everything you do has no way to help us.

Maybe you are looking for