I’m currently trying to update my in house search engine to use multiple words. It’s very big and complicated but I’m running into errors I never ran into before now and I have no idea why.
so the question is, why am I receiving the error below?
I’m going to split this up into different sections for better understanding.
This is just the SQL query that I echod, copy and pasted into PHPMyAdmin, pasted here (PHPMyAdmin formatted it nicely) It searches for 2 words in the database:
SELECT *
FROM (
SELECT p.page_url AS url, COUNT( * ) AS occurrences
FROM PAGE p, word w, occurrence o
WHERE (
(
p.page_id = o.page_id
AND w.page_word_id = o.page_word_id
AND w.word_word LIKE '%' 'test' '%'
GROUP BY p.page_id
)
OR (
p.page_id = o.page_id
AND w.page_word_id = o.page_word_id
AND w.word_word LIKE '%' 'search' '%'
GROUP BY p.page_id
)
UNION (
SELECT f.file_url AS url, COUNT( * ) AS occurrences
FROM files f, filenames fn, fileoccurrence fo
WHERE f.file_id = fo.file_id
AND fn.file_word_id = fo.file_word_id
AND fn.file_word LIKE '%' 'test' '%'
GROUP BY f.file_id
)
OR (
SELECT f.file_url AS url, COUNT( * ) AS occurrences
FROM files f, filenames fn, fileoccurrence fo
WHERE f.file_id = fo.file_id
AND fn.file_word_id = fo.file_word_id
AND fn.file_word LIKE '%' 'search' '%'
GROUP BY f.file_id
)
)t
ORDER BY occurrences DESC
This code is produced by this PHP code below which uses the explode function from the search input
// Do a little formatting
$keyword = strtolower($keyword);
// Get timestamp for start
$start_time = microtime(true);
$searched_words = explode(' ', $keyword);
foreach ($searched_words as $index => $word) {
// Set up the stemmer
$stemmer = new PorterStemmer;
$stemmed_string = $stemmer->stem($word);
$searched_words[$index] = $stemmed_string;
}
// Configure the sql code
$sql = "SELECT * FROM (SELECT p.page_url AS url, COUNT(*) AS occurrences
FROM page p, word w, occurrence o WHERE (";
// Add the extra words to the sql
foreach ($searched_words as $index => $word) {
$sql .= "(p.page_id = o.page_id AND w.page_word_id = o.page_word_id
AND w.word_word LIKE '%' '" . $word . "' '%' GROUP BY p.page_id) OR";
}
// Add the union to the sql and then add the second query
$sql = substr($sql, 0, (strLen($sql)-3)); //this will eat the last OR
$sql .= " UNION ";
// The second set of querys
foreach ($searched_words as $index => $word) {
$sql .= "(SELECT f.file_url AS url, COUNT(*) AS occurrences FROM files f, filenames fn, fileoccurrence fo
WHERE f.file_id = fo.file_id AND fn.file_word_id = fo.file_word_id AND fn.file_word
LIKE '%' '" . $word . "' '%' GROUP BY f.file_id) OR";
}
// Clsoe the sql code
$sql = substr($sql, 0, (strLen($sql)-3)); //this will eat the last OR
$sql .= ") t ORDER BY occurrences DESC"; // LIMIT " . $results . "");
// echo the query for the pure lolz of it
echo $sql . "<br /><br />";
// Search the DB for the results
$results = mysql_query($sql)
or die("Invalid query: " . mysql_error());
All of this returns the error:
Invalid query: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near ‘GROUP BY p.page_id) OR(p.page_id = o.page_id AND
w.page_word_id = o.page_word_id’ at line 3
Why am I receiving this error? The code I used previously worked fine. The only real thing I added was the foreach().
This is my original SQL code:
$result = mysql_query("SELECT * FROM (SELECT p.page_url AS url, COUNT(*) AS occurrences
FROM page p, word w, occurrence o WHERE p.page_id = o.page_id AND w.page_word_id = o.page_word_id
AND w.word_word LIKE '%' '" . $stemmed_string . "' '%' GROUP BY p.page_id UNION
SELECT f.file_url AS url, COUNT(*) AS occurrences FROM files f, filenames fn, fileoccurrence fo
WHERE f.file_id = fo.file_id AND fn.file_word_id = fo.file_word_id AND fn.file_word
LIKE '%' '" . $stemmed_string . "' '%' GROUP BY f.file_id) t ORDER BY occurrences DESC") // LIMIT " . $results . "")
or die("Invalid query: " . mysql_error());
EDIT: Fixed the above error. with this code
// Configure the sql code
$sql = "SELECT * FROM (SELECT p.page_url AS url, COUNT(*) AS occurrences
FROM page p, word w, occurrence o WHERE (";
// Add the extra words to the sql
foreach ($searched_words as $index => $word) {
$sql .= "(p.page_id = o.page_id AND w.page_word_id = o.page_word_id
AND w.word_word LIKE CONCAT('%', '" . $word . "', '%'))) OR "; //GROUP BY p.page_id)
}
// Add the union to the sql and then add the second query
$sql = substr($sql, 0, (strLen($sql)-4)); //this will eat the last OR
$sql .= " GROUP BY p.page_id)";
$sql .= " UNION ";
$sql .= "(SELECT f.file_url AS url, COUNT(*) AS occurrences FROM files f, filenames fn, fileoccurrence fo
WHERE (";
// The second set of querys
foreach ($searched_words as $index => $word) {
$sql .= "(f.file_id = fo.file_id AND fn.file_word_id = fo.file_word_id AND fn.file_word
LIKE CONCAT('%', '" . $word . "', '%'))) OR "; //GROUP BY f.file_id)
}
// Clsoe the sql code
$sql = substr($sql, 0, (strLen($sql)-4)); //this will eat the last OR
$sql .= " GROUP BY f.file_id)";
$sql .= ") t ORDER BY occurrences DESC"; // LIMIT " . $results . "");
This now produces error:
Invalid query: Every derived table must have its own alias
which has something to do with the unions (i’m not very good at unions.. or SQL in general)
You can’t concatenate strings in SQL just by placing them next to each other.
Should be
Or if you use
SET SQL_MODE='PIPES_AS_CONCAT'to get standard ANSI SQL syntax, you can use:Re your comment, I see another problem:
In SQL, the WHERE clause must be complete before you can add a GROUP BY clause. The syntax is:
Whereas you have:
What you have is not legal syntax.
Really, this is the kind of thing you should be able to look up yourself in any beginner reference on SQL.
This means that you used a subquery in the FROM clause but did not give it an alias. For example:
If you leave out the
AS xthen it’s an error (x is just an example in this case, you can choose a more meaningful alias).