如何在 WHERE 子句中使用计算值?
Posted
技术标签:
【中文标题】如何在 WHERE 子句中使用计算值?【英文标题】:How can I use a calculated value in the WHERE clause? 【发布时间】:2019-10-25 10:17:06 【问题描述】:我有以下 SQL:
SELECT members.id, FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25) as age
FROM members
JOIN crew_cv ON members.id=crew_cv.user_id
WHERE members.active=1 AND age>20 AND age<30
ORDER BY crew_cv.last_name, crew_cv.first_name
LIMIT 0,30
#1054 - Unknown column 'age' in 'where clause'
如何在WHERE
子句中使用计算出的值age
?
【问题讨论】:
见:Why should I provide an MCRE for what seems to me to be a very simple SQL query? 【参考方案1】:在sql中你不能在where子句中使用别名(你必须重复列代码)
SELECT members.id, FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25) as age
FROM members
JOIN crew_cv ON members.id=crew_cv.user_id
WHERE members.active=1 AND FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25)>20
AND age<FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25)
ORDER BY crew_cv.last_name, crew_cv.first_name
LIMIT 0,30
但你可以创建一个视图
create view my_view as
select members.id, crew_cv.last_name, crew_cv.first_name , FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25) as age
FROM members
JOIN crew_cv ON members.id=crew_cv.user_id
WHERE members.active=1
然后
SELECT id, age, last_name, first_name
from my_view
where age>20 AND age<30
ORDER BY last_name, first_name
LIMIT 0,30
或将条件应用到有子句
在 sql 中,子句按特定顺序进行评估 在 select 子句之前评估 where 条件(因此在此阶段不知道列别名) 而是在 select 子句之后评估 have 子句
【讨论】:
【参考方案2】:FROM clause
ON clause
OUTER clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
DISTINCT clause
ORDER BY clause
TOP clause
这是查询执行的顺序,这意味着在您的查询中(在 where 子句中)在定义(在 select 子句中)之前使用计算。
如果您仍想将所有内容放在一个查询中,这是我建议的查询:
SELECT members.id, temp.age
FROM members,
(SELECT user_id, crew_cv.last_name, crew_cv.first_name
FLOOR(DATEDIFF('2019-10-25', crew_cv.dob) / 365.25) as age
FROM crew_cv) as temp
WHERE members.id = temp.user_id
AND members.active=1
AND temp.age > 20 AND temp.age < 30
ORDER BY temp.last_name, temp.first_name
LIMIT 0,30
【讨论】:
【参考方案3】:Maxim 已经回答了问题,但删除了答案。
MySQL 扩展了HAVING
子句,因此即使在没有聚合的查询中也能正常工作。这允许它使用别名过滤查询——这很方便。所以:
SELECT m.id,
FLOOR(DATEDIFF('2019-10-25', c.dob) / 365.25) as age
FROM members m JOIN
crew_cv c
ON m.id = c.user_id
WHERE m.active = 1
HAVING age > 20 AND age < 30
ORDER BY c.last_name, c.first_name
LIMIT 0, 30;
MySQL 这样做是因为它倾向于实现子查询。这增加了读取和写入数据的开销。在大多数其他数据库中,您只需使用子查询或 CTE 来表达这一点,而不会影响性能。 MySQL 重载 HAVING
作为替代方法。
而且,话虽如此,/ 365.25
是一个近似值。更准确的查询是:
SELECT m.id,
FLOOR(DATEDIFF('2019-10-25', c.dob) / 365.25) as age
FROM members m JOIN
crew_cv c
ON m.id = c.user_id
WHERE m.active = 1 AND
c.dob >= DATE('2019-10-25') - INTERVAL 30 YEAR AND
c.dob <= DATE('2019-10-25') - INTERVAL 21 YEAR
ORDER BY c.last_name, c.first_name
LIMIT 0, 30;
如果 MySQL 认为合适,它还可以使用(dob)
上的索引。
【讨论】:
以上是关于如何在 WHERE 子句中使用计算值?的主要内容,如果未能解决你的问题,请参考以下文章
Drupal 8 和 PostgreSQL:如何在 WHERE 子句中使用表达式的结果?
如何在光标的 select 语句 where 子句中传递逗号分隔值
如何在 SQL Server where 子句中使用表值函数