0

考虑以下示例查询:

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在查询中稍后提供?我更喜欢这个,因为我相信如果可能的话,将代码维护在一个地方就足够了。

4

3 回答 3

1

列别名问题中所述

WHERE标准 SQL 不允许在子句中引用列别名。施加此限制是因为在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子句中(其中别名列已经被计算并且因此可用) - 但性能会受到影响,因为无法使用索引并且在编译结果之前不会应用过滤器。

于 2013-07-22T10:36:05.143 回答
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()
于 2013-07-22T10:38:04.353 回答
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()
于 2013-07-22T10:41:03.957 回答