在稍后的查询中使用AS值

时间:2013-07-22 10:33:44

标签: mysql sql

考虑以下示例查询:

SELECT foo.bar,
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted
) as bazValue
FROM foo
WHERE bazValue >= CURDATE() # <-- This doesn't work

如何在查询中稍后提供bazValue?我更喜欢这个,因为我认为如果可能的话,将代码保存在一个地方就足够了。

3 个答案:

答案 0 :(得分:1)

正如Problems with Column Aliases所述:

  

标准SQL不允许在WHERE子句中引用列别名。强制执行此限制是因为在评估WHERE子句时,可能尚未确定列值。例如,以下查询是非法的:

SELECT id, COUNT(*) AS cnt FROM tbl_name
 WHERE cnt > 0 GROUP BY id;
     

WHERE子句确定GROUP BY子句中应包含哪些行,但它引用的列别名是在选择行之后才知道的,并按GROUP BY

然而,您可以重用别名表达式,如果它使用确定性函数,查询优化器将确保重用缓存结果:

SELECT foo.bar,
       DATEDIFF(
         -- your arguments
       ) as bazValue
FROM   foo
WHERE  DATEDIFF(
         -- your arguments
       ) >= CURDATE()

或者,您可以将过滤器移动到HAVING子句(其中已经计算了别名列,因此可用) - 但是由于无法使用索引而且性能将受到影响,并且过滤器将不会应用结果编制完成后。

答案 1 :(得分:1)

由于MySQL不支持CTE,请考虑使用inline view

SELECT foo.bar,
FROM foo, 
(SELECT DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted
    ) as bazValue
) AS iv
WHERE iv.bazValue >= CURDATE()

答案 2 :(得分:1)

您可以在MySQL中使用以下几种解决此问题的方法:

通过使用内联视图(这应该适用于大多数其他版本的SQL):

select * from
(SELECT foo.bar,
 DATEDIFF(
     # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted
 ) as bazValue
 FROM foo) buz
WHERE bazValue >= CURDATE()

通过使用HAVING子句(在HAVING子句中使用列别名特定于MySQL):

SELECT foo.bar,
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted
) as bazValue
FROM foo
HAVING bazValue >= CURDATE()