巨大的sql查询返回错误(mysql)


Huge sql query returning an error (mysql)

我目前正在尝试更新我的内部搜索引擎,使其使用多个单词。这是非常大和复杂的,但我遇到了以前从未遇到过的错误,我不知道为什么。

所以问题是,为什么我会收到下面的错误?

为了更好地理解,我将把它分成不同的部分。

这只是我echod复制并粘贴到PHPMyAdmin中的SQL查询,粘贴在这里(PHPMyAdmin很好地格式化了它)它在数据库中搜索2个单词:

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 

这段代码是由下面的PHP代码生成的,它使用了来自搜索输入的分解函数

// 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());

所有这些都返回错误:

无效查询:您的SQL语法有错误;查看手册对应于您的MySQL服务器版本,以获得正确的语法在"GROUP BY p.page_id"附近使用)或(p.page_id=o.page_id ANDw.page_word_id=第3行处的o.page_word_I'

为什么我收到这个错误?我以前使用的代码运行良好。我添加的唯一真实的东西是foreach()

这是我的原始SQL代码:

$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:修复了上述错误。使用此代码

//  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 . "");

这现在产生错误:

无效查询:每个派生表都必须有自己的别名

这与并集有关(我不太擅长并集…或一般的SQL)

在SQL中,不能仅通过将字符串并排放置来连接字符串。

AND w.word_word LIKE '%' 'test' '%'

应该是

AND w.word_word LIKE CONCAT('%', 'test', '%')

或者,如果您使用SET SQL_MODE='PIPES_AS_CONCAT'来获得标准的ANSI SQL语法,您可以使用:

AND w.word_word LIKE '%' || 'test' || '%'

关于你的评论,我看到了另一个问题:

在SQL中,必须先完成WHERE子句,然后才能添加GROUP BY子句。语法为:

WHERE ( <conditions...> )
GROUP BY <expressions>

而你有:

WHERE ( <conditions...> GROUP BY <expressions> ) 
   OR ( <conditions...> GROUP BY <expressions> )

你所拥有的不是合法的语法。

实际上,这是您应该能够在任何SQL初学者参考资料中查找到的东西。


每个派生表都必须有自己的别名

这意味着您在FROM子句中使用了一个子查询,但没有给它一个别名。例如:

SELECT ... FROM (SELECT ... FROM table) AS x WHERE ...etc... 

如果省略了AS x,则这是一个错误(在这种情况下,x只是一个示例,您可以选择一个更有意义的别名)。

在生成的SQL中,括号不匹配。。。有9个和8个。

作为上一次代码更改的一部分,您是否也注释掉了LIMIT " . $results . "");