2010-11-26 6 views
1

Jusqu'à présent, j'ai les suivantes:Oracle SQL Mois précédent numéro de requête

SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month", 
     TO_CHAR(sysdate, 'mm')-1 as "Current_Month" 
    FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES" 
WHERE "Depart_Month" = "Current_Month" 

Cependant, cela me donne une erreur:

ORA-00904: "Current_Month": invalid identifier

Toutefois, sans la clause WHERE, il fonctionne très bien. Des idées?

Répondre

2

Malheureusement, vous ne pouvez pas référencer les alias de colonne dans la clause WHERE car ils ne sont pas encore disponibles. Vous pouvez faire ceci:

select TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month", 
      TO_CHAR(sysdate, 'mm')-1 as "Current_Month" 
from  "HOL_DEPART_DATES" "HOL_DEPART_DATES" 
where  TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') = TO_CHAR(sysdate, 'mm')-1 

ou faire:

select "Depart_Month", "Current_Month" 
from 
(select TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month", 
      TO_CHAR(sysdate, 'mm')-1 as "Current_Month" 
    from  "HOL_DEPART_DATES" "HOL_DEPART_DATES" 
) 
where  "Depart_Month" = "Current_Month" 
+0

sur place, tous les deux, fait beaucoup plus de sens maintenant! – Coffeee

2

la clause SELECT est évaluée après la clause WHERE dans SQL. C'est pourquoi la clause WHERE ne peut pas voir les alias que vous avez définis.

Soit:

  • course une sous-requête:

    SELECT "Depart_Month", "Current_Month" 
        FROM (SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') 
            AS "Depart_Month", 
           TO_CHAR(SYSDATE, 'mm') - 1 AS "Current_Month" 
          FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES") 
    WHERE "Depart_Month" = "Current_Month" 
    
  • ou utiliser l'expression dans la clause where:

    SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') AS "Depart_Month", 
         TO_CHAR(SYSDATE, 'mm') - 1 AS "Current_Month" 
        FROM "HOL_DEPART_DATES" "HOL_DEPART_DATES" 
    WHERE TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') 
         = TO_CHAR(SYSDATE, 'mm') - 1 
    
1

Je resterais loin de l'exécution arithmétique sur la valeur de retour fr om TO_CHAR. Lorsque vous soustrayez 1 de la chaîne '01' (januari), nous ne terminerons pas avec 12 (décembre).

Vous devriez faire quelque chose comme ceci:

select * 
    from hol_depart_dates 
where depart_date between trunc(add_months(sysdate, -1), 'MM') 
         and trunc(sysdate, 'MM') - interval '1' second; 

Maintenant, la requête peut utiliser un index sur depart_date. Et TO_CHAR n'a pas besoin d'être appelé pour chaque ligne.

+0

Parce que vous soustrayez une journée entière de TRUNC (SYSDATE, 'MM'), vous manquez effectivement toutes les dates de départ qui sont le dernier jour du mois (sauf si leur heure est exactement minuit). –

+0

Opps, bien repéré. C'est corrigé maintenant. – Ronnis

0

Si vous voulez comparer des dates, vous ne devriez pas les convertir en chaînes - Oracle a intégré le support de l'arithmétique date/heure.

Dans votre cas, il semble que vous interrogiez la table où le mois de la date de départ est égal au mois précédent - ce qui n'a pas de sens. Si c'est en novembre, la requête retournera les lignes d'octobre 2010, octobre 2009, octobre 2008, etc. Etes-vous sûr que c'est ce que vous vouliez? L'une des meilleures façons d'utiliser l'arithmétique de date pour déterminer si une date est dans le mois précédent est d'utiliser une combinaison de TRUNC (date, 'MONTH'), qui renvoie le premier jour du mois en cours, avec ADD_MONTHS (date, -1), qui obtient la date un mois avant.

SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month", 
     TO_CHAR(ADD_MONTHS(sysdate, -1), 'mm') as "Current_Month" 
FROM "HOL_DEPART_DATES" 
WHERE "HOL_DEPART_DATES"."DEPART_DATE" 
     BETWEEN ADD_MONTHS(TRUNC(SYSDATE,'MONTH'),-1) 
     AND  TRUNC(SYSDATE,'MONTH') - 0.00001; 

Le "0,00001" soustraient une seconde du jour, de sorte que la plage de dates devient effective (en supposant qu'il est maintenant Novembre 2010) 01-Oct-2010 au 31-00:00:00 Oct-2010 23: 59:59.

Une syntaxe alternative équivalente serait:

SELECT TO_CHAR("HOL_DEPART_DATES"."DEPART_DATE", 'MM') as "Depart_Month", 
     TO_CHAR(ADD_MONTHS(sysdate, -1), 'mm') as "Current_Month" 
FROM "HOL_DEPART_DATES" 
WHERE "HOL_DEPART_DATES"."DEPART_DATE" 
     >= ADD_MONTHS(TRUNC(SYSDATE,'MONTH'),-1) 
AND  "HOL_DEPART_DATES"."DEPART_DATE" < TRUNC(SYSDATE,'MONTH');