web-dev-qa-db-fra.com

Utiliser un alias dans une clause WHERE

J'ai une requête qui est destinée à me montrer toutes les lignes de la table A qui n'ont pas été mises à jour assez récemment. (Chaque ligne doit être mise à jour dans les 2 mois suivant "mois_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 sont acceptés ...)

64
JPLemme

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

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

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

Des informations intéressantes sont venues des commentaires:

Il ne devrait y avoir aucune baisse de performance . Oracle n'a pas besoin de se matérialiser requêtes internes avant d'appliquer outer conditions - Oracle examinera transformer cette requête en interne et Enfoncez le prédicat dans le .__ intérieur. requête et le fera si cela coûte efficace. - Justin Cave

107
Tomalak
 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
12
me_an

Ou vous pouvez avoir votre alias dans une clause HAVING

9
James

Juste comme une approche alternative à vous pouvez 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 file d'attente et la sélectionner dans cette vue.

CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
2
J-Alex

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

Une sous-requête ne permet pas nécessairement une liaison appropriée aux colonnes de la table référencée, contrairement à 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 .

0
Peter Aylett