views:

127

answers:

3

I have a SQL that can be simplified to:

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

You can see there is a duplicate of "LOCATE( column, :keyword )". Is there a way to calculate it only once ?

+5  A: 
SELECT *, LOCATE( column, :keyword ) AS somelabel 
FROM table 
WHERE somelabel > 0 
ORDER BY somelabel
Jeff Ober
But I got an error on MySQL #1054 - Unknown column 'c1' in 'where clause'The SQL is:SELECT *, LOCATE(name, 'a') AS c1 FROM `employees` WHERE c1 > 0
Cheng
This method won't work for all databases. Some will still require you to explicitly reference the function in the ordering clause.
Sonny Boy
Does this even work for MySQL? http://dev.mysql.com/doc/refman/5.4/en/select.html "It is not allowable to refer to a column alias in a WHERE clause, because the column value might not yet be determined when the WHERE clause is executed"
CodeByMoonlight
Jeff, which database support this? MySQL does not.
Cheng
The AS keyword? Most should. If MySQL cannot do it, try performing the SELECT in a subquery and apply the WHERE to that.
Jeff Ober
...see JosephStyons's answer.
Jeff Ober
+2  A: 

Jeff Ober has the right idea, but here is an alternative method:

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
JosephStyons
+2  A: 

HAVING works with aliases in MySQL:

SELECT *, LOCATE( column, :keyword ) AS somelabel 
FROM table 
HAVING somelabel > 0 
ORDER BY somelabel
Cixate
Note that HAVING calculates the entire result set and then filters it. WHERE filters row by row, saving memory.
Jeff Ober
Not only memory, if the condition can be evaluated from a loaded indexes it might be saving I/O as well.
Unreason