【问题标题】:Using an Alias in a WHERE clause在 WHERE 子句中使用别名
【发布时间】:2010-09-26 06:44:10
【问题描述】:

我有一个查询,旨在向我显示表 A 中最近没有足够更新的任何行。 (每行应在“month_no”之后的 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 Invalid Identifier”错误。不用说,我不想在 WHERE 子句中重复整个 DECODE 函数。有什么想法吗? (接受修复和解决方法...)

【问题讨论】:

    标签: sql oracle alias decode ora-00904


    【解决方案1】:

    这是不可能的,因为按时间顺序,WHERE 发生在 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
    

    从 cmets 上移了一些有趣的信息:

    应该不会影响性能。 Oracle 不需要实现 应用外部之前的内部查询 条件——甲骨文将考虑 在内部转换此查询并 将谓词下推到内部 查询,如果有成本就会这样做 有效的。 – Justin Cave

    【讨论】:

      【解决方案2】:

      或者您可以在HAVING 子句中使用您的别名

      【讨论】:

      • 这将是一个有趣的方法,你能给出任何代码吗?
      • 适用于何处的规则相同,因此这不是解决方案。
      • 我被困在 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%' 失败(“'where 子句'中的未知列'x'”)
      【解决方案3】:
       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 是真正的答案。 HAVING 是计算列的子句检查器,如COUNTMAXSELECT 查询中的其他表达式,因为它过滤最终获取的数据。
      【解决方案4】:

      正如您可以做的另一种方法:

      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;
      

      【讨论】:

        【解决方案5】:

        可以有效地定义一个可以在 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
        

        Syed Mehroz Alam致敬。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-20
          • 1970-01-01
          • 2011-03-15
          • 2020-05-14
          • 1970-01-01
          • 2012-01-12
          相关资源
          最近更新 更多