Reputation:
I have built a basic search engine which is almost functional. I am using UNION
in the query in order to search for an specific value in two tables blog
and pages
. I am also using PDO style. There are a total of 13 rows. When I perform the query with keyword blah
which is found in every column of both tables. I only get 5 results back from SELECT COUNT(*) FROM blog
and nothing back from SELECT COUNT(*) FROM pages
. Also I am using a prepare statement for :searchquery => $serachquery
that stores the keyword value but when echoing the value I get :searchquery
instead of blah
. How can I display the correct results? DEMO
PHP
<?php
include("db_con/db_con.php");
$search_output = "";
if(isset($_POST['searchquery']) && $_POST['searchquery'] != ""){
$searchquery = preg_replace('#[^a-z 0-9?!]#i', '', $_POST['searchquery']);
if($_POST['filter1'] == "All Tables"){
$sqlCommand = "(SELECT COUNT(*) FROM blog WHERE blog_title LIKE :searchquery OR blog_body LIKE :searchquery) UNION (SELECT COUNT(*) FROM pages WHERE page_title LIKE :searchquery OR page_body LIKE :searchquery) ";
}
$sql_prepare = $db_con->prepare($sqlCommand);
if($sql_prepare->execute( array("searchquery"=>'%'.$searchquery.'%') )){
$count = $sql_prepare->fetchColumn();
if($count > 1){
$search_output .= "<hr />$count results for <strong>$searchquery</strong><hr />$sqlCommand";
} else {
$search_output = "<hr />0 results for <strong>$searchquery</strong>$sqlCommand<hr />";
}
}
}
?>
HTML
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
Search For:
<input name="searchquery" type="text" size="44" maxlength="88">
Within:
<select name="filter1">
<option value="All Tables">All Tables</option>
</select>
<input name="myBtn" type="submit">
Upvotes: 1
Views: 1899
Reputation: 92815
First of all UNION
happened* (see a note below) to give you in your case two rows in the resultset.
| COUNT(*) | |----------| | 5 | -- with fetchColumn() you read a value of only the first row | 8 |
but you fetch only a value of the first row. That's why you always get 5
instead of 13
Note: the usage of UNION
in your particular case is invalid because it returns only distinct values. This means if both selects happened to have the same value (e.g. 5
) then your result set would've looked like this
| COUNT(*) | |----------| | 5 |
instead of
| COUNT(*) | |----------| | 5 | | 5 |
You might've used UNION ALL
instead of UNION
and either iterated over the resultset and got the sum in php, or used an outer SELECT
with an aggregate function SUM()
.
Now to get the total count you can simply do this
SELECT
(
SELECT COUNT(*)
FROM blog
WHERE blog_title LIKE :searchquery
OR blog_body LIKE :searchquery
) +
(
SELECT COUNT(*)
FROM pages
WHERE page_title LIKE :searchquery
OR page_body LIKE :searchquery
) total
Output:
| TOTAL | |-------| | 13 |
Here is SQLFiddle demo
Now as far as php code goes
1) this check
if($count > 1)...
is incorrect and actually useless since you can legitimately get only one hit by your search criteria and COUNT()
always return a value be it 0
or some other positive integer. Therefore you can simply leave the only line
$search_output .= "<hr />$count results for <strong>$searchquery</strong><hr />$sqlCommand";
^^^^^^^^^^^
2) You see placeholders :search query
when you output the query because you output the raw sql query from $sqlCommand
variable.
Upvotes: 0
Reputation: 740
now replace this line :
$count = $sql_prepare->fetchColumn();
with this :
$count = 0;
foreach($sql_prepare->fetchall() as $records)
{
$count += $records[0];
}
it returns count of all rows;
Upvotes: 1
Reputation: 873
I made a sqlfiddle: http://sqlfiddle.com/#!2/82482/3
As you see your query returns two rows - this might be your problem. You can enhance your query to sum the both results:
SELECT SUM(results)
FROM
(SELECT COUNT(*) as results
FROM blog
WHERE blog_title LIKE '%blah%' OR blog_body LIKE '%blah%'
UNION
SELECT COUNT(*) as results
FROM pages
WHERE page_title LIKE '%blah%' OR page_body LIKE '%blah%') a
Upvotes: 0