Oracle SQL Previous Month query issue
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?
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"
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');
精彩评论