Pergunta

So far I've got the following:

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"

However this gives me an error:

ORA-00904: "Current_Month": invalid identifier

However without the WHERE clause, it works fine. Any ideas?

Foi útil?

Solução

Unfortunately you cannot reference the column aliases in the WHERE clause as they are not yet available. You can either do this:

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

or do this:

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"

Outras dicas

the SELECT clause is evaluated after the WHERE clause in SQL. This is why the WHERE clause can't see the aliases you have defined.

Either:

  • run a subquery:

    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"
    
  • or use the expression in the where clause:

    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
    

I would stay away from performing arithmtic on the return value from TO_CHAR. When subtracting 1 from the string '01' (januari) we won't end up with 12 (december).

You should do something like this:

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

Now the query can use an index on depart_date. And TO_CHAR does not have to be called for every row.

If you want to compare dates, you should not convert them to strings - Oracle has builtin support for date/time arithmetic.

In your case, it seems you're querying the table where the month of the departure date is equal to the month previous - which doesn't make sense. If it is currently November, then the query would return rows from October 2010, October 2009, October 2008, etc. Are you sure that's what you wanted?

One of the best ways to use date arithmetic to determine if a date is within the previous month is to use a combination of TRUNC(date,'MONTH'), which returns the first day of the current month, with ADD_MONTHS(date,-1), which gets the date one month prior.

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;

The "0.00001" subtracts one second from the date, so the date range effectively becomes (assuming it is now November 2010) 01-Oct-2010 00:00:00 to 31-Oct-2010 23:59:59.

An alternative, equivalent syntax would be:

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');
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top