考虑以下示例查询:
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
?我更喜欢这个,因为我认为如果可能的话,将代码保存在一个地方就足够了。
答案 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()