在WHERE子句中使用别名
在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 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)) > TO_NUMBER(TO_CHAR(B.last_update_date, 'YYYYMM'))
WHERE子句中的最后一行导致“ORA-00904 Invalid Identifier”错误。毋庸置疑,我不想在WHERE子句中重复整个DECODE函数。有什么想法?(接受修复和解决方法...)
在使用WHERE子句中使用别名时出现的问题是,WHERE子句在查询执行的早期阶段处理,而别名是在查询执行的后期阶段创建的。因此,当我们在WHERE子句中使用别名时,MySQL无法识别该别名。
要解决这个问题,可以使用HAVING子句来代替WHERE子句。在HAVING子句中使用别名是可以的,因为HAVING子句在查询执行的晚期阶段处理,此时别名已经创建。
以下是在使用别名的WHERE子句中遇到问题的代码示例:
SELECT CONCAT(names, surname) AS x FROM clients WHERE x LIKE '%a%'
解决方法是将WHERE子句中的别名替换为原始的列名或表达式。以下是将上述代码示例中的别名替换为原始列名的示例:
SELECT CONCAT(names, surname) AS x FROM clients WHERE CONCAT(names, surname) LIKE '%a%'
通过这种方式,我们可以避免在使用WHERE子句时出现未知列的错误,并正确地使用别名进行查询筛选。
使用别名的原因是为了简化查询语句中的列名和表达式,使其更易读和理解。在上述代码中,使用了别名来表示两个计算列:MONTH_NO和UPD_DATE。
然而,代码中存在一个问题:在WHERE子句中使用了别名,即.identifier = B.identifier。这是错误的,因为WHERE子句在数据被检索之前进行过滤,它无法识别别名。
为了解决这个问题,可以使用HAVING子句来过滤别名列。HAVING子句在数据被检索之后进行过滤,可以识别别名。因此,我们可以将WHERE子句中的条件移动到HAVING子句中,即HAVING MONTH_NO > UPD_DATE。
下面是修改后的代码:
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 HAVING MONTH_NO > UPD_DATE
通过将条件移动到HAVING子句中,我们可以正确地使用别名来进行过滤,从而解决了原始代码中的问题。