在WHERE子句中使用别名

我有一个查询是为了向我显示表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无效标识符”错误。 不用说,我不想在我的WHERE子句中重复整个DECODE函数。 有什么想法吗? (接受这两个修补程序和解决方法…)

这是不可能的,因为按照时间顺序,WHERE发生 SELECT 之前 ,这总是执行链中的最后一步。

你可以做一个子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将考虑在内部转换此查询,并将谓词向下推入到内部查询中,如果成本效益好,则会这样做。 – 贾斯汀洞穴

  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 

您也可以为您的队列创build永久视图,并从视图中进行select。

 CREATE OR REPLACE VIEW_1 AS (SELECT ...); SELECT * FROM VIEW_1;