Sql 在WHERE子句中使用别名

Sql 在WHERE子句中使用别名,sql,oracle,alias,decode,ora-00904,Sql,Oracle,Alias,Decode,Ora 00904,我有一个查询,用于显示表a中最近没有更新的任何行。每行应在月号之后的2个月内更新: SELECT A.identifier , A.name , TO_NUMBER(DECODE( A.month_no , 1, 200803 , 2, 200804 , 3, 200805 , 4, 200806 , 5, 200807

我有一个查询,用于显示表a中最近没有更新的任何行。每行应在月号之后的2个月内更新:

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子句中重复整个DECODE函数。有什么想法吗?修复和解决方案都被接受…

这不可能直接实现,因为按时间顺序,在选择之前发生,选择始终是执行链中的最后一步

您可以对其进行子选择和筛选:

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将考虑的条件 在内部和外部转换此查询 将谓词向下推到内部 查询,如果是成本,则会这样做 有效


或者,您可以在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和其他子句中使用

子查询不一定允许对引用的表列进行适当的绑定,但是外部应用允许

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

值得称赞。

这将是一个有趣的方法,你能给出任何代码吗?适用于何处的规则相同,因此这不是一个解决方案。我被MySQL 5.5卡住了,不知道这是否适用于Oracle。但是:从具有类似于“%a%”的x的客户机中选择CONCATnames,姓氏为x有效,而从具有类似于“%a%”的x失败的客户机中选择CONCATnames,姓氏为x,其中“WHERE子句”中的未知列“x”是真正的答案。HAVING是SELECT查询中计算列(如COUNT、MAX和其他表达式)的子句检查器,因为它过滤最终获取的数据。
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