Использование псевдонима в предложении WHERE
Вопрос
У меня есть запрос, который предназначен для того, чтобы показать мне любые строки в таблице А, которые не были обновлены достаточно недавно.(Каждая строка должна быть обновлена в течение 2 месяцев после "month_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
Последняя строка в предложении WHERE вызывает ошибку "Недопустимый идентификатор ORA-00904".Излишне говорить, что я не хочу повторять всю функцию ДЕКОДИРОВАНИЯ в моем предложении WHERE.Есть какие-нибудь мысли?(Принимаются как исправления, так и обходные пути ...)
Решение
Это невозможно напрямую, потому что хронологически, ГДЕ происходит до того , как ВЫБЕРИТЕ, который всегда является последним шагом в цепочке выполнения.
Вы можете сделать дополнительный выбор и отфильтровать по нему:
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
Интересная информация появилась в комментариях:
Не должно быть никакого снижения производительности.Oracle не нужно материализовать внутренний запросов перед нанесением наружный условия -- Oracle будет рассматривать преобразование этого запроса внутренне и нажимаем предикат во внутреннюю запрос и будет делать это, если это экономически эффективные.– Джастин Кейв
Другие советы
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
Или вы можете использовать свой псевдоним в HAVING
оговорка
Так же, как альтернативный подход к вам, вы можете сделать:
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
Также вы можете создать постоянное представление для своей очереди и выбрать из представления.
CREATE OR REPLACE VIEW_1 AS (SELECT ...);
SELECT * FROM VIEW_1;
Можно эффективно определить переменную, которая может использоваться как в предложениях SELECT, WHERE, так и в других.
Вложенный запрос не обязательно допускает соответствующую привязку к столбцам таблицы, на которые даны ссылки, однако 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
Престижность для Сайед Мехроз Алам.