PHP和子句不显示结果,但显示OR
我有一个图书搜索,它正在搜索我正在寻找的书籍,它搜索的书籍共享作者类别或出版商。我已经设置了它,它适用于OR子句,例如,有一个类别的书籍儿童或与他们相关的历史,这是正确的,但当我搜索属于两个类别(和)的书籍时,例如儿童和魔法(哈利波特),它不会显示这些书籍,即使它们在数据库中链接。 以上是我使用或搜索属于儿童和历史的书籍时所做的搜索 上面你们可以看到,当哈利波特的书确实属于这两本书时,我并没有得到关于分享儿童和魔法的书的结果。 上面是数据库中的链接,它为每本书提供了它们的分类,Magic是分类1,Childrens是分类2,你可以看到它们都共享这些 下面是该查询的PHP代码PHP和子句不显示结果,但显示OR,php,mysql,sql,database,phpmyadmin,Php,Mysql,Sql,Database,Phpmyadmin,我有一个图书搜索,它正在搜索我正在寻找的书籍,它搜索的书籍共享作者类别或出版商。我已经设置了它,它适用于OR子句,例如,有一个类别的书籍儿童或与他们相关的历史,这是正确的,但当我搜索属于两个类别(和)的书籍时,例如儿童和魔法(哈利波特),它不会显示这些书籍,即使它们在数据库中链接。 以上是我使用或搜索属于儿童和历史的书籍时所做的搜索 上面你们可以看到,当哈利波特的书确实属于这两本书时,我并没有得到关于分享儿童和魔法的书的结果。 上面是数据库中的链接,它为每本书提供了它们的分类,Magic是
<?php
include 'header.php';
include 'searchscriptTEST.php';
$sql = "SELECT DISTINCT bk.title AS Title, bk.bookid AS BookID, bk.year AS Year, bk.publisher AS Publisher, aut.authorname AS Author
FROM book bk
JOIN book_category bk_cat
ON bk_cat.book_id = bk.bookid
JOIN categories cat
ON cat.id = bk_cat.category_id
JOIN books_authors bk_aut
ON bk_aut.book_id = bk.bookid
JOIN authors aut
ON aut.id = bk_aut.author_id";
if(isset($_GET['searchInput'])){
$input = $_GET['searchInput'];
$input = preg_replace('/[^A-Za-z0-9]/', '', $input);
}
if (isset($input)){
$getters = array();
$queries = array();
foreach ($_GET as $key => $value) {
$temp = is_array($value) ? $value : trim($value);
if (!empty($temp)){
if (!in_array($key, $getters)){
$getters[$key] = $value;
}
}
}
if (!empty($getters)) {
foreach($getters as $key => $value){
//${$key} = $value;
switch ($key) {
case 'searchInput':
array_push($queries,"(bk.title LIKE '%{$getters['searchInput']}%'
|| bk.description LIKE '%{$getters['searchInput']}%' || bk.isbn LIKE '%{$getters['searchInput']}%'
|| bk.keywords LIKE '%{$getters['searchInput']}%' || aut.authorname LIKE '%{$getters['searchInput']}%')");
break;
case 'srch_publisher':
array_push($queries, "(bk.publisher = '{$getters["srch_publisher"]}')");
break;
case 'Year':
if(isset($getters['Year1']) ==""){
array_push($queries, "(bk.year = '{$getters['Year']}')");
} else {
array_push($queries, "(bk.year BETWEEN '$value' AND '{$getters['Year1']}')");
}
break;
case 'srch_author':
if(isset($getters['authorOperator']) ==""){
array_push($queries, "(bk_aut.author_id = '{$getters["srch_author"]}')");
} else {
$operator = $getters['authorOperator'];
array_push($queries, "(bk_aut.author_id = '$value' $operator bk_aut.author_id = '{$getters['srch_author1']}')");
}
break;
case 'srch_category':
if(isset($getters['catOperator']) ==""){
array_push($queries, "(bk_cat.category_id = '{$getters["srch_category"]}')");
} else {
$operator1 = $getters['catOperator'];
array_push($queries, "(bk_cat.category_id = '$value' $operator1 bk_cat.category_id = '{$getters['srch_category1']}')");
}
break;
}
}
}
if(!empty($queries)){
$sql .= " WHERE ";
$i = 1;
foreach ($queries as $query) {
if($i < count($queries)){
$sql .= $query." AND ";
} else {
$sql .= $query;
}
$i++;
}
}
$sql .= " GROUP BY bk.title ORDER BY bk.title ASC";
var_dump($sql);
}else{
$sql .= " GROUP BY bk.title ORDER BY bk.title ASC";
}
$rs = mysql_query($sql) or die(mysql_error());
$rows = mysql_fetch_assoc($rs);
$tot_rows = mysql_num_rows($rs);
?>
在格式化查询以使其实际可读后,您将看到以下行:
bk_cat.category_id = '2' AND bk_cat.category_id = '1'
这样不行,category\u id
不能同时是2
和1
您的查询应该类似于:
SELECT books.*
FROM books
JOIN book_categories bc1 ON books.id = bc1.book_id AND bc1.category_id = 1
JOIN book_categories bc2 ON books.id = bc2.book_id AND bc1.category_id = 2
您需要在类别上加入两次,或者在需要匹配的类别上加入两次。在格式化查询以使其实际可读后,您会看到以下行:
bk_cat.category_id = '2' AND bk_cat.category_id = '1'
这样不行,category\u id
不能同时是2
和1
您的查询应该类似于:
SELECT books.*
FROM books
JOIN book_categories bc1 ON books.id = bc1.book_id AND bc1.category_id = 1
JOIN book_categories bc2 ON books.id = bc2.book_id AND bc1.category_id = 2
您需要在类别上加入两次
JOIN
,或者加入的次数与您要匹配的类别相同。有多种方法可以做到这一点,但最简单的方法是使用WHERE
子句(类似于这样的子句)来选择属于多个类别的书籍:
WHERE
`bk`.`book_id` IN (SELECT `book_id` FROM `book_category` WHERE `category_id` = '2')
AND `bk`.`book_id` IN (SELECT `book_id` FROM `book_category` WHERE `category_id` = '1')
有多种方法可以做到这一点,但最简单的方法是使用类似这样的WHERE
子句来选择属于多个类别的书籍:
WHERE
`bk`.`book_id` IN (SELECT `book_id` FROM `book_category` WHERE `category_id` = '2')
AND `bk`.`book_id` IN (SELECT `book_id` FROM `book_category` WHERE `category_id` = '1')
我认为这是可行的,但效率很低。现在,您强制MySQL始终选择一个类别中的所有书籍。它无法进行优化。@doge Correct这在较大的结果集上可能会变得效率低下。对于较小的结果集,可读性很好。@AeroX yes u legend有效,我将测试它的作者和发布者,但我相信它会很好,谢谢:D@Doge我刚刚在生产环境MS-SQL Server上做了一个测试,从类似的查询中得到的查询计划会导致嵌套循环(内部连接)
。我假设MySQL查询规划器选择做类似的事情(不过我目前没有访问MySQL服务器的权限来测试这一点)。您可以运行EXPLAIN[query]
了解运行查询需要做些什么。我认为这是可行的,但效率很低。现在你强迫MySQL总是选择一个类别中的所有书籍。它无法优化。@doge Correct这在较大的结果集上可能会变得效率低下。但对于较小的结果集,可读性很好。@AeroX yes u lege我会测试它的作者和出版商,但我相信它会很好地工作。谢谢:D@Doge我刚刚在生产环境MS-SQL Server上做了一个测试,从类似的查询中得到的查询计划会导致嵌套循环(内部联接)
。我假设MySQL查询规划器选择做类似的事情(不过我目前没有访问MySQL服务器的权限来测试这个问题)。您可以运行EXPLAIN[query]
了解运行查询需要做什么。我没有了解$operator1在数组推送函数中扮演的角色我没有了解$operator1在数组推送函数中扮演的角色