如何消除 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 FROM employees 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 中的重复计算?的主要内容,如果未能解决你的问题,请参考以下文章

MS Access SQL 如何消除重复值

如何使用SQL语句消除重复列

SQL severa 中l数据库如何进行查询

如何在SQL Server中消除重复和合并列值到单个文本

Ms Access SQL:如何防止 Select 查询重复

如何消除左连接中的重复记录?