在 WHERE 子句中使用别名
Posted
技术标签:
【中文标题】在 WHERE 子句中使用别名【英文标题】:Using an Alias in a WHERE clause 【发布时间】: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 函数。有什么想法吗? (接受修复和解决方法...)
【问题讨论】:
【参考方案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
是计算列的子句检查器,如COUNT
、MAX
和SELECT
查询中的其他表达式,因为它过滤最终获取的数据。【参考方案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致敬。
【讨论】:
以上是关于在 WHERE 子句中使用别名的主要内容,如果未能解决你的问题,请参考以下文章