Использовать псевдоним в предложении where
У меня есть запрос, который должен показать мне любые строки в таблице A, которые не были обновлены достаточно недавно. (Каждая строка должна быть обновлена в течение 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. Есть мысли? (Оба исправления и обходные пути приняты...)
5 ответов:
это невозможно напрямую, потому что хронологически, где происходит до выберите, что всегда является последним шагом в цепочке выполнения.
вы можете сделать суб-выбор и фильтр на нем:
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
Так же, как альтернативный подход к вам можно сделать:
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, так и в других предложениях.
подзапрос не обязательно допускает соответствующую привязку к столбцам ссылочной таблицы, однако внешний 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
спасибо Сайед Алам Mehroz.