如何在SQL中消除重复计算?

4
我可以将一个 SQL 简化为以下形式:

SELECT * 
  FROM table 
 WHERE LOCATE( column, :keyword ) > 0 
ORDER BY LOCATE( column, :keyword )

你可以看到有一个“LOCATE(column,:keyword)”的重复。有没有一种方法只计算一次?

1
此外,如果您不知道的话,许多数据库允许您在函数或计算上创建索引。因此,如果您发现自己正在执行基于LOCATE(column,:keyword)的大量查询,您可以创建一个索引,在其中预先计算和存储该值,以提高查询速度。 - Peter Recore
1
你确定 LOCATE 被调用了两次吗? - tster
tster是正确的 - 许多SQL引擎都会对此进行优化。 - Jeff Ober
我的目的不仅是为了节省计算,还要使SQL清晰易懂。因为上面的例子是一个简化的例子,在我的情况下,实际的SQL可能很容易就会达到6行以上。 - Cheng
3个回答

5
SELECT *, LOCATE( column, :keyword ) AS somelabel 
FROM table 
WHERE somelabel > 0 
ORDER BY somelabel

但是我在MySQL上遇到了一个错误#1054 - 'where clause'中的未知列'c1'SQL语句如下: SELECT *,LOCATE(name,'a')AS c1 FROM employees WHERE c1 > 0 - Cheng
这种方法并不适用于所有数据库。有些数据库仍然需要您在排序子句中明确引用函数。 - Sonny Boy
这对MySQL有效吗?http://dev.mysql.com/doc/refman/5.4/en/select.html “在WHERE子句中引用列别名是不允许的,因为当执行WHERE子句时,列值可能尚未确定。” - MartW
Jeff,哪个数据库支持这个?MySQL不支持。 - Cheng
AS关键字?大多数情况下应该可以。如果MySQL无法执行,请尝试在子查询中执行SELECT并将WHERE应用于其中。 - Jeff Ober
请查看JosephStyons的答案。 - Jeff Ober

2

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

2

在MySQL中,HAVING子句可以与别名一起使用:

SELECT *, LOCATE( column, :keyword ) AS somelabel 
FROM table 
HAVING somelabel > 0 
ORDER BY somelabel

1
请注意,HAVING 计算整个结果集,然后进行过滤。WHERE 逐行过滤,节省内存。 - Jeff Ober
不仅如此,如果条件可以从加载的索引中进行评估,那么也可能节省I/O。 - Unreason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接