1

Let's say your running a query and you have a lot of different user inputs that may not find an exact match. Now would it be possible to do something like the following?

$query = "SELECT *,
              CASE matchingValues
                  WHEN $field1 LIKE '$a' THEN value = '1' ELSE value = '0'
                  WHEN $field2 LIKE '$b' THEN value = '1' ELSE value = '0'
                  WHEN $field3 LIKE '$c' THEN value = '1' ELSE value = '0'
                  WHEN $field4 LIKE '$d' THEN value = '1' ELSE value = '0'
                  WHEN $field5 LIKE '$e' THEN value = '1' ELSE value = '0'
              END AS score
              FROM . $usertable
              WHERE
                  $field1 LIKE '$a' AND
                  $field2 LIKE '$b' AND
                  $field3 LIKE '$c' AND
                  $field4 LIKE '$d' AND
                  $field5 LIKE '$d'
              ORDER BY score DESC";

if($result = mysql_query($query)) {

    if(mysql_num-rows($result)==NULL) {
    echo 'No Results Found';

    }else{

    ....
gen_Eric
  • 223,194
  • 41
  • 299
  • 337
CWF010
  • 55
  • 3

1 Answers1

2

Yes this is possible, though you would do it without the WHERE clause, and you would want to add up all the inputs instead of using a CASE to get the total score. Since each LIKE statement returns a boolean 1 or 0, you can just add them up to find out how many matches you have. A HAVING clause then limits to rows returned with a score > 0, if you want to return only those that actually matched.

  SELECT *,
      (($field1 LIKE '$a') +
      ($field2 LIKE '$b') +
      ($field3 LIKE '$c') +
      ($field4 LIKE '$d') +
      ($field5 LIKE '$e')) AS score
  FROM . $usertable
  HAVING score > 0
  ORDER BY score DESC";

We assume you have already added % wildcards to the LIKE variables, and that they have been properly escaped prior to use in your query.

However, while you can do it this way (a poor-man's full-text search), MySQL offers the possibility of creating a full text index across multiple columns on MyISAM tables.

Update: To artificially weight them...

If you have a need to weight them, use CASE statements and put in higher numbers for the top few:

  SELECT *,
      (CASE WHEN ($field1 LIKE '$a') THEN 5 ELSE 0 END +
      CASE WHEN ($field2 LIKE '$b') THEN 4 ELSE 0 END +
      CASE WHEN ($field3 LIKE '$c') THEN 3 ELSE 0 END +
      CASE WHEN ($field4 LIKE '$d') THEN 2 ELSE 0 END +
      CASE WHEN ($field5 LIKE '$e') THEN 1 ELSE 0 END) AS score
  FROM . $usertable
  HAVING score > 0
  ORDER BY score DESC";

To just enforce that the first one match, put it in your WHERE clause.

  SELECT *,
      (($field1 LIKE '$a') +
      ($field2 LIKE '$b') +
      ($field3 LIKE '$c') +
      ($field4 LIKE '$d') +
      ($field5 LIKE '$e')) AS score
  FROM . $usertable
  WHERE $field1 LIKE '$a'
  HAVING score > 0
  ORDER BY score DESC";

Again, to be clear - a very closely related functionality is already built-in and optimized in MySQL's full text indexing and the MATCH keyword.

Community
  • 1
  • 1
Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • Michael, that code works great. However the data sets returned may be all over the place. Is there a way to hone in on say `$field1` and make sure that field is always true. Otherwise a user may input something into `$field1` that they really need, but the result may not match up with their input? – CWF010 Jul 19 '12 at 20:25
  • Michael, that is fantastic. This has been killing me the last 2 days trying so many different things. Thanks again. – CWF010 Jul 19 '12 at 20:39