如何消除 SQL 中的重复计算?
Posted
技术标签:
【中文标题】如何消除 SQL 中的重复计算?【英文标题】:How to eliminate duplicate calculation in SQL? 【发布时间】:2009-10-20 15:55:11 【问题描述】:我有一个可以简化为的 SQL:
SELECT *
FROM table
WHERE LOCATE( column, :keyword ) > 0
ORDER BY LOCATE( column, :keyword )
您可以看到“LOCATE(column, :keyword)”的副本。有没有办法只计算一次?
【问题讨论】:
另外,如果您不知道,许多数据库允许您为函数或计算创建索引。因此,如果您发现自己基于 LOCATE(column,:keyword) 进行了大量查询,您可以创建一个索引,其中该值已预先计算和存储,以提高查询速度。 你确定 LOCATE 被调用了两次吗? tster 是正确的 - 许多 sql 引擎会优化它。 我的目的不仅仅是为了节省计算,还要让SQL清晰。因为上面的例子是一个简化的例子,所以在我的例子中,实际的 SQL 可能很容易达到 6 整行。 【参考方案1】:SELECT *, LOCATE( column, :keyword ) AS somelabel
FROM table
WHERE somelabel > 0
ORDER BY somelabel
【讨论】:
但我在 mysql #1054 上遇到错误 - 'where 子句'中的未知列 'c1' SQL 是:SELECT *, LOCATE(name, 'a') AS c1 FROMemployees
WHERE c1 > 0
此方法不适用于所有数据库。有些仍然需要您在 ordering 子句中明确引用该函数。
这甚至适用于 MySQL 吗? dev.mysql.com/doc/refman/5.4/en/select.html "不允许在 WHERE 子句中引用列别名,因为执行 WHERE 子句时可能尚未确定列值"
Jeff,哪个数据库支持这个? MySQL 没有。
AS 关键字?大多数应该。如果 MySQL 不能这样做,请尝试在子查询中执行 SELECT 并将 WHERE 应用于该查询。【参考方案2】:
HAVING 可以在 MySQL 中使用别名:
SELECT *, LOCATE( column, :keyword ) AS somelabel
FROM table
HAVING somelabel > 0
ORDER BY somelabel
【讨论】:
请注意,HAVING 会计算整个结果集,然后对其进行过滤。 WHERE 逐行过滤,节省内存。 不仅是内存,如果可以从加载的索引中评估条件,它也可能会节省 I/O。【参考方案3】:Jeff Ober 的想法是正确的,但这里有另一种方法:
SELECT
t.*
,loc.LOCATED
FROM
table t
INNER JOIN
(
SELECT
primary_key
,LOCATE(column,:keyword) AS LOCATED
FROM
table
) loc
ON t.primary_key = loc.primary_key
WHERE loc.LOCATED > 0
ORDER BY
loc.LOCATED
【讨论】:
以上是关于如何消除 SQL 中的重复计算?的主要内容,如果未能解决你的问题,请参考以下文章