dimanche 19 novembre 2017

ORA-01417 - une manière de traiter...

Je cherchais quelques informations relatives à deux immobilisations…
SELECT '2017' Exercice,fb.book_type_code livre_FA,livre.name livre_GL,livre.currency_code Devise
          ,fbc.book_class type_livre, fa.asset_type type_bien
          ,(fb.original_cost) coût_origine,(Fb.Cost) cout_actuel
      ,(fb.cost-NVL(fds.deprn_reserve, fb.cost)) vnc
FROM fa_additions fa
      ,fa_books fb
    ,fa_book_controls fbc
    ,gl_ledgers livre
    ,fa_deprn_periods fdp
    ,fa_deprn_summary fds
WHERE fa.asset_id = fb.asset_id
  AND fb.book_type_code = fbc.book_type_code
  AND livre.ledger_id = fbc.set_of_books_id
  AND to_date('31102017','DDMMYYYY') between fb.date_effective AND NVL(fb.DATE_INEFFECTIVE,sysdate)
  AND fbc.date_ineffective is NULL
  AND fbc.book_class = 'CORPORATE'
  AND fa.creation_date < to_date('31102017','DDMMYYYY')
  AND fds.asset_id = fb.asset_id
   AND fds.book_type_code = fdp.book_type_code
   AND fdp.book_type_code = fb.book_type_code
   AND fds.period_counter = fdp.period_counter
   AND fdp.period_name = 'OCT-17'
  AND NOT EXISTS (SELECT 1 FROM FA_TRANSACTION_HEADERS t, fa_retirements cession
                             WHERE t.asset_id = fa.asset_id
                                AND t.book_type_code = fb.book_type_code
                                AND t.transaction_type_code = 'FULL RETIREMENT'
                                AND t.asset_id = cession.asset_id
                                AND cession.book_type_code = fb.book_type_code
                                AND cession.transaction_header_id_in = t.transaction_header_id
                                AND cession.status = 'PROCESSED'
                                AND  XXCM_FA_COMMUN.get_date_comptable(t.book_type_code, t.Asset_Id, t.Transaction_Type_Code, t.transaction_header_id) <= to_date('31102017','DDMMYYYY')
                           OR
  (t.transaction_date_entered<= to_date ('31102017','DDMMYYYY') and cession.cost_retired=0 ))
                         )
  AND fa.asset_number IN ('085199900215-1' ,'BC00000190-2');
 
Mais la requête ne ramène les informations que pour l’une des deux…


 
  
Ceci provient du fait que malheureusement l’une des deux est complétement amortie, la jointure avec la table des amortissements doit être retravaillée. Essayons de positionner une jointure externe...

Externalisation des jointures :
AND fds.asset_id (+)= fb.asset_id
AND fds.book_type_code (+)= fdp.book_type_code
AND fds.period_counter (+)= fdp.period_counter

C'est là qu'apparaît un message d’erreur ORA-01417
ORA-01417: une table peut être de jointure externe pour une autre table au moins

 

 
Solution : fabriquer une table virtuelle (faire une SELECT de SELECT) dans le FROM, ce qui permettra de ne faire qu’une seule jointure, ou prendre le dernier amortissement présent (celui correspondant à la période la plus récente).
Dans le from, ajout de la table immo_amort en lieu et place des tables fa_deprn_periods et fa_deprn_summary : mon credo est que lorsqu’il n’y a pas de période pour une immobilisation, c’est que l’immobilisation est complètement amortie et donc la valeur net comptable (VNC) résiduelle est nulle.
On fait maintenant la jointure externe sur cette nouvelle table imo_amort.

 
SELECT fa.asset_number,fa.asset_id,'2017' Exercice, fb.book_type_code livre_FA,livre.name livre_GL, livre.currency_code Devise
             ,fbc.book_class type_livre, fa.asset_type type_bien
             ,(fb.original_cost) coût_origine,(Fb.Cost) cout_actuel
     ,(fb.cost-NVL(immo_amort.deprn_reserve,fb.cost)) vnc,immo_amort.deprn_reserve
 FROM fa_additions fa
            ,fa_books fb
     ,fa_book_controls fbc
     ,gl_ledgers livre
     , (SELECT fds.asset_id,fds.book_type_code,fds.deprn_reserve
          FROM fa_deprn_periods fdp
              ,fa_deprn_summary fds
         WHERE fds.book_type_code = fdp.book_type_code
                          and fds.period_counter = fdp.period_counter
           AND fdp.period_name = 'OCT-17') immo_amort
WHERE fa.asset_id = fb.asset_id
  AND fb.book_type_code = fbc.book_type_code
  AND livre.ledger_id = fbc.set_of_books_id
  AND to_date('31102017','DDMMYYYY') between fb.date_effective AND NVL(fb.DATE_INEFFECTIVE,sysdate)
  AND fbc.date_ineffective is NULL
  AND fbc.book_class = 'CORPORATE'
  AND fa.creation_date < to_date('31102017','DDMMYYYY')
  AND immo_amort.asset_id (+)= fb.asset_id
  AND immo_amort.book_type_code (+)= fb.book_type_code
  AND NOT EXISTS (SELECT 1 FROM FA_TRANSACTION_HEADERS t, fa_retirements cession
                                              WHERE t.asset_id = fa.asset_id
                                                    AND t.book_type_code = fb.book_type_code
                                                    AND t.transaction_type_code = 'FULL RETIREMENT'
                                                    AND t.asset_id = cession.asset_id
                                                    AND cession.book_type_code = fb.book_type_code
                                 AND cession.transaction_header_id_in = t.transaction_header_id
                                                    AND cession.status = 'PROCESSED'
                                                    AND (XXCM_FA_COMMUN.get_date_comptable (t.book_type_code, t.Asset_Id , t.Transaction_Type_Code, t.transaction_header_id) < to_date('31102017','DDMMYYYY')
OR
(t.transaction_date_entered<= to_date ('31102017','DDMMYYYY') and cession.cost_retired=0 ))
                                                            )
  AND fa.asset_number IN ('085199900215-1','BC00000190-2');

Résultat : on a bien les deux lignes, il n'y a pas de valeur de deprn_reserve sur la seconde ligne (d'où la nécessité d'avoir fait une jointure externe).

 

PS : en général VNC = Coût – amortissements cumulés