views:

233

answers:

2

Please check out the following query. The SQL isn't as bad as it looks. Basically, we have a fact table and some simple joins to some dimension tables. Then we have a join to a derived table, given the alias ACCOUNTS-DIM-DEP

  SELECT dw_mgr.fa_trans_fct.period,
         dw_mgr.fa_trans_fct.asset_cost_company_code,
         dw_mgr.fa_trans_fct.asset_cost_center_id,
         dw_mgr.fa_trans_fct.depreciation_account_id,
         accounts_dim_dep.description, 
         dw_mgr.projects_dim.project_num,
         dw_mgr.projects_dim.project_name,
         ROUND (dw_mgr.fa_trans_fct.activity_deprn_amount_us, 2),
         organizations_cost.major_geography,
         organizations_cost.business_unit || organizations_cost.bu_desc,
         organizations_cost.industry_sector_num
              ||organizations_cost.industry_sector_desc,
         hyperion_organizations.hyperion_num,
         hyperion_organizations.hyperion_desc,
         hyperion_organizations.hyperion_reporting
    FROM dw_mgr.fa_trans_fct,
         (SELECT DISTINCT flex_value account_id, description
                     FROM rf_fnd_flex_values_det
                    WHERE flex_value_set_id = '1002363' 
                      AND summary_flag = 'N') accounts_dim_dep,
         dw_mgr.projects_dim,
         dw_mgr.organizations organizations_cost,
         dw_mgr.organizations hyperion_organizations
   WHERE 
         --Fact to Org on Company Code / Cost Center
         (dw_mgr.fa_trans_fct.asset_cost_center_id   
                                     = organizations_cost.cost_center_id)
     AND (dw_mgr.fa_trans_fct.asset_cost_company_code 
                                     = organizations_cost.company_code)
     --Fact to Projects Dim on Proj Num
     AND (dw_mgr.projects_dim.project_num = dw_mgr.fa_trans_fct.project_num)
     --Fact to Accounts_Dim_Dep on Account ID
     --convert account_ID on left to_number??????
     AND (accounts_dim_dep.account_id 
                            = dw_mgr.fa_trans_fct.depreciation_account_id) 
     --Fact Hyp Company Code Cost Center to Hyp Org
     AND (hyperion_organizations.cost_center_id 
                            = dw_mgr.fa_trans_fct.asset_cost_center_id AND
          hyperion_organizations.company_code  
                            = dw_mgr.fa_trans_fct.asset_cost_company_code)
   --Filters
     AND (
          dw_mgr.fa_trans_fct.period IN ('01-Jun-2009')
          --works
          --AND dw_mgr.fa_trans_fct.asset_cost_center_id IN ('000296') 
          --does not work               
          AND dw_mgr.fa_trans_fct.asset_cost_center_id IN ('000296','000296') 
          AND dw_mgr.fa_trans_fct.asset_cost_company_code = '0007'
         )



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

  Statement Id=4203172   Type=
  Cost=2.64018716311899E-308  TimeStamp=06-10-09::17::51:43

       (1)  SELECT STATEMENT  CHOOSE 
     Est. Rows: 1  Cost: 6
       (14)  NESTED LOOPS 
     Est. Rows: 1  Cost: 6
           (11)  NESTED LOOPS 
                Est. Rows: 1  Cost: 5
               (9)  HASH JOIN 
                    Est. Rows: 1  Cost: 3
                   (3)  TABLE TABLE ACCESS BY INDEX ROWID DW_MGR.ORGANIZATIONS  [Analyzed] 
                   (3)   Blocks: 1,669 Est. Rows: 1 of 31,748  Cost: 1 
                        Tablespace: DIM_DATA
                       (2)  INDEX (UNIQUE) INDEX UNIQUE SCAN DW_MGR.ORG_PK  [Analyzed] 
                            Est. Rows: 1  Cost: 1
                   (8)  PARTITION RANGE SINGLE 
                        Est. Rows: 7  Cost: 1
                       (7)  PARTITION LIST ALL 
                            Est. Rows: 7  Cost: 1
                           (6)  TABLE TABLE ACCESS BY LOCAL INDEX ROWID DW_MGR.FA_TRANS_FCT  [Analyzed] 
                                Blocks: 1,431,026 Est. Rows: 7 of 32,900,663  Cost: 1
                               (5)  BITMAP CONVERSION TO ROWIDS
                                   (4)  INDEX (BITMAP) BITMAP INDEX SINGLE VALUE DW_MGR.FA_TRANS_AST_COMP_CC_BM_I
               (10)  REMOTE REMOTE.RF_FND_FLEX_VALUES_DET 
                    Est. Rows: 1  Cost: 2
           (13)  TABLE TABLE ACCESS BY INDEX ROWID DW_MGR.PROJECTS_DIM  [Analyzed] 
           (13)   Blocks: 12,184 Est. Rows: 1 of 163,117  Cost: 1 
                Tablespace: PROJECT_DATA
               (12)  INDEX (UNIQUE) INDEX UNIQUE SCAN DW_MGR.PROJECTS_UI  [Analyzed] 
                    Est. Rows: 1  Cost: 1

The users were complaining that when their WebI (business intelligence) report included multiple COST CENTERS in their filter, resulting in a SQL with an "IN" include multiple values, the following error was returned:

   [1]: (Error): ORA-01722: invalid number ORA-02063: preceding line from [dbname]

Otherwise, for a single COST CENTER, the report worked fine. The interesting part is that I noticed that the following join condition, which to me appears UNRELATED, was negatively impacting the SQL:

accounts_dim_dep.account_id = dw_mgr.fa_trans_fct.depreciation_account_id

The problem here is that the column on the left, accounts_dim_dep.account_id, is defined in the db as a charchar and the col on the right, dw_mgr.fa_trans_fct.depreciation_account_id, is defined as a number.

When I modified the join condition to convert the number to a varchar...

accounts_dim_dep.account_id 
                       = to_char(dw_mgr.fa_trans_fct.depreciation_account_id)

...the SQL works regardless of the number of COST CENTERS that are specified in the filter.


I'd like to know how a type mismatch on one seemingly unrelated column affects the whether one can specify multiple COST CENTERS in the IN list.

+2  A: 

If you had PLW errors enabled, you'd have been alerted to the situation earlier - you'd have gotten a "conversion away from type" error. I re-wrote your query:

SELECT t.period,
       t.asset_cost_company_code,
       t.asset_cost_center_id,
       t.depreciation_account_id,
       add.description, 
       pd.project_num,
       pd.project_name,
       ROUND(t.activity_deprn_amount_us, 2),
       o.major_geography,
       o.business_unit || o.bu_desc,
       o.industry_sector_num || o.industry_sector_desc,
       o.hyperion_num,
       o.hyperion_desc,
       o.hyperion_reporting
  FROM DW_MGR.FA_TRANS_FCT t
  JOIN DW_MGR.PROJECTS_DIM pd ON pd.project_num = t.project_num
  JOIN DW_MGR.ORGANIZATIONS o ON o.cost_center_id = t.asset_cost_center_id
                             AND o.company_code = t.asset_cost_company_code
  JOIN (SELECT TO_NUMBER(rffvd.flex_value) 'account_id',
               rffvd.description
          FROM RF_FND_FLEX_VALUES_DET rffvd
         WHERE rffvd.flex_value_set_id = '1002363' 
           AND rffvd.summary_flag = 'N'
      GROUP BY rffvd.flex_value,
               rffvd.description) add ON add.account_id = t.depreciation_account_id
 WHERE t.period IN ('01-Jun-2009')
   AND t.asset_cost_center_id IN ('000296','000296') --doesn't work        
   AND t.asset_cost_company_code = '0007'

Changelog:

  • Save yourself some typing by using table aliases (also makes it easier for others to read & help)
  • Removed: hyperion_organization was a join to the same table, using the same criteria
  • Specified TO_NUMBER(RF_FND_FLEX_VALUES_DET.flex_value) so the conversion occurs before the JOIN

I don't know why the ORA error would occur on 2+ entries in the IN clause, but it you provide two of the same as you posted then it's not likely to be a data issue.

OMG Ponies
OMG Ponies
+5  A: 

The ORA-02063 error means that the ORA-01722 error occurs in a remote database. That fits with the fact that (according to the explain plan) the RF_FND_FLEX_VALUES_DET table is remote.

The value accounts_dim_dep.account_id is an alias for a flex_value, which appears to be a varchar2 and almost certainly contains non-numeric values. When you compare it to a numeric column Oracle applies an implicit TO_NUMBER() to it, which fails with the ORA-01722 if it hits a value which is not a number. By converting dw_mgr.fa_trans_fct.depreciation_account_id to a string you avoid the implicit conversion.

So why does the original query succeed when you only have one cost centre but fail when you have several? Without having access to your data to run some tests, or at the very least the explain plans for the different versions, it is hard to be sure. But the explain plan you have published shows that the remote operation retrieves just the one row from RF_FND_FLEX_VALUES_DET. I'm guessing that when you run the query with multiple cost centres it pulls back a fistful of rows, which include some where flex_value has a non-numeric value.

APC
We can only guess, but APC answer is probably near the real cause. I had similar error messages, when oracle query optimizer decided to do a type conversion other as expected. It is error prune to use implicit type conversion, because oracle sometimes converts from string to number if it thinks query goes faster this way.
Christian13467