Использование псевдонима в предложении 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 Invalid Identifier». Излишне говорить, что я не хочу повторять всю функцию DECODE в моем предложении WHERE. Какие-нибудь мысли? (Исправления и обходные пути приняты ...)

10.12.2008 16:31:39
5 ОТВЕТОВ
РЕШЕНИЕ

Это невозможно напрямую, потому что в хронологическом порядке ГДЕ происходит перед SELECT, который всегда является последним шагом в цепочке выполнения.

Вы можете сделать дополнительный выбор и отфильтровать его:

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 рассмотрит возможность преобразования этого запроса внутри себя и вставит предикат во внутренний запрос и сделает это, если это будет экономически эффективным. - Джастин Кейв

110
23.05.2017 12:17:42

Или вы можете иметь свой псевдоним в HAVINGпункте

10
24.02.2012 18:12:01
Это был бы интересный подход, вы можете дать какой-нибудь код?
rob5408 15.11.2010 02:16:31
то же самое правило, что и в случае применения, так что это не решение.
Alexey 13.11.2015 16:44:39
Я застрял на MySQL (5.5), не знаю, относится ли это к Oracle. НО: SELECT CONCAT(names, surname) AS x FROM clients HAVING x LIKE '%a%' работает, а SELECT CONCAT(names, surname) AS x FROM clients WHERE x LIKE '%a%'терпит неудачу («Неизвестный столбец« x »в«
fr13d 3.12.2015 11:23:10
 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
14
21.03.2012 19:58:45
HAVINGэто реальный ответ. HAVINGявляется средством проверки предложений для вычисляемых столбцов, например COUNT, MAXи других выражений в SELECTзапросе, поскольку оно фильтрует окончательно извлеченные данные.
George Dimitriadis 30.12.2019 16:02:24

Так же как альтернативный подход вы можете сделать:

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;
2
14.02.2017 05:49:23

Можно эффективно определить переменную, которая может использоваться как в предложениях 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

Престижность Сайед Mehroz Алам .

0
17.04.2018 13:22:22