Utiliser un alias dans une clause WHERE

J’ai une requête qui vise à me montrer toutes les lignes du tableau A qui n’ont pas été mises à jour assez récemment. (Chaque ligne doit être mise à jour dans les 2 mois suivant “month_no”.):

SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier AND MONTH_NO > UPD_DATE 

La dernière ligne de la clause WHERE provoque une erreur “ORA-00904 Invalid Identifier”. Inutile de dire que je ne veux pas répéter toute la fonction DECODE dans ma clause WHERE. Des pensées? (Les correctifs et les solutions de contournement ont été acceptés …)

Ce n’est pas possible directement, car chronologiquement, WHERE se produit avant SELECT, qui est toujours la dernière étape de la chaîne d’exécution.

Vous pouvez faire une sous-sélection et la filtrer:

 SELECT * FROM ( SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier ) AS inner_table WHERE MONTH_NO > UPD_DATE 

Un peu intéressant d’informations a été relevé des commentaires:

Il ne devrait y avoir aucun impact sur la performance. Oracle n’a pas besoin de matérialiser des requêtes internes avant d’appliquer des conditions externes – Oracle envisagera de transformer cette requête en interne et de pousser le prédicat dans la requête interne et le fera si cela est rentable. – Grotte de Justin

  SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE FROM table_a A, table_b B WHERE .identifier = B.identifier HAVING MONTH_NO > UPD_DATE 

Ou vous pouvez avoir votre alias dans une clause HAVING

Tout comme une approche alternative à vous faire:

 WITH inner_table AS (SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) as MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE FROM table_a A , table_b B WHERE A.identifier = B.identifier) SELECT * FROM inner_table WHERE MONTH_NO > UPD_DATE 

Vous pouvez également créer une vue permanente pour votre queue et sélectionner un affichage.

 CREATE OR REPLACE VIEW_1 AS (SELECT ...); SELECT * FROM VIEW_1; 

Il est possible de définir efficacement une variable pouvant être utilisée dans les clauses SELECT, WHERE et autres.

Une sous-requête n’autorise pas nécessairement une liaison appropriée aux colonnes de la table référencée, à la différence de OUTER APPLY.

 SELECT A.identifier , A.name , vars.MONTH_NO , TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM')) as UPD_DATE FROM table_a A , table_b B ON A.identifier = B.identifier OUTER APPLY ( SELECT -- variables MONTH_NO = TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807 , 6, 200808 , 7, 200809 , 8, 200810 , 9, 200811 , 10, 200812 , 11, 200701 , 12, 200702 , NULL)) ) vars WHERE vars.MONTH_NO > UPD_DATE 

Félicitations à Syed Mehroz Alam .