【问题标题】:How to eliminate duplicate calculation in SQL?如何消除 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 整行。

标签: sql mysql query-optimization


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多