2008-12-10 7 views
59

J'ai une requête destinée à afficher les lignes du tableau A qui n'ont pas été mises à jour assez récemment. (Chaque ligne doit être mis à jour dans les 2 mois après "month_no".):Utilisation d'un alias dans une clause WHERE

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 Identifiant non valide". Inutile de dire que je ne veux pas répéter toute la fonction DECODE dans ma clause WHERE. Des pensées? (Les deux correctifs et solutions de contournement acceptés ...)

Répondre

100

Ceci n'est pas possible directement, car chronologiquement, O WH arrive avant SELECT, qui est toujours la dernière étape de la chaîne d'exécution.

Vous pouvez faire une sous-sélection et le filtre sur elle:

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 

bit Intéressant d'information est passé de commentaires:

Il devrait y avoir aucun impact sur les performances. Oracle n'a pas besoin de se matérialiser requêtes internes avant d'appliquer extérieures conditions - Oracle examinera transformer cette requête en interne et pousser le prédicat vers le bas dans la requête intérieure et le fera si elle est le coût efficace. - Justin Cave

9

Ou vous pouvez avoir votre alias dans une HAVING clause

+4

Ce serait une approche intéressante, pouvez-vous donner un code? – rob5408

+0

la même règle quant à où s'applique, donc ce n'est pas une solution. – Alexey

+0

Je suis coincé sur MySQL (5.5), je ne sais pas si cela s'applique à Oracle. MAIS: 'SELECT CONCAT (nom, prénom) AS x FROM clients AYANT x LIKE '% a%'' fonctionne, alors que 'SELECT CONCAT (noms, prénoms) AS x FROM clients O WH x LIKE'% a% ' 'fails (" Unknown column 'x' dans 'where clause' ") – fr13d

12
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 
1

Tout comme une approche alternative que 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 votre file d'attente et sélectionnez à partir de la vue.

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