Reputation: 91
I'm creating a search box that queries two MySQL tables and lists the results in real time. For now though, I have a working prototype that will query only one table. I've written the following PHP code in conjunction with JQuery and it works wonderfully:
HTML
<input onkeyup="search(this);" type="text">
<ol id="search-results-container"></ol>
Javascript
function search(input) {
var inputQuery = input.value;
/* $() creates a JQuery selector object, so we can use its html() method */
var resultsList = $(document.getElementById("search-results-container"));
//Check if string is empty
if (inputQuery.length > 0) {
$.get("search-query.php", {query: inputQuery}).done(function(data) {
//Show results in HTML document
resultsList.html(data);
});
}
else { //String query is empty
resultList.empty();
}
}
and PHP
<?php
include("config.php"); //database link
if(isset($_REQUEST["query"])) {
$sql = "SELECT * FROM students WHERE lastname LIKE ? LIMIT 5";
/* Creates $stmt and checks if mysqli_prepare is true */
if ($stmt = mysqli_prepare($link, $sql)) {
//Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_query);
//set parameters
$param_query = $_REQUEST["query"] . '%';
//Try and execute the prepared statement
if (mysqli_stmt_execute($stmt)) {
$result = mysqli_stmt_get_result($stmt);
//get number of rows
$count = mysqli_num_rows($result);
if ($count > 0) {
//Fetch result rows as assoc array
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
echo "<h1>Students:</h1>"; //Header indicates student list
for ($i = 0; $i < $count; $i++) {
$name = $row["lastname"];
echo "<p>$name</p>";
}
}
else { //Count == 0
echo "No matches found.<br>";
}
}
else { //Execution of preped statement failed.
echo "Could not execute MySQL query.<br>";
}
} // end mysqli_prepare
} // end $_RESQUEST isset
?>
The details of the students
table are arbitrary, except for the fact that it has a String column that lists the student's last name.
My problem is that there is also a staff
table which is effectively the same as students
but for a different purpose. I'd like to query the staff
table at the same time as students
, but have the results separated like so:
<h1>Students:</h1>
<p>Student1</p>
<p>Student2</p>
<h1>Staff</h1>
<p>Staff1</p>
<p>Staff2</p>
The obvious answer would be to add another $sql
statement similar to the one on Line 5 and just do both queries serially - effectively doubling the search time - but I'm concerned this will take too long. Is this a false assumption (that there will be a noticeable time difference), or is there actually a way to do both queries alongside each other? Thanks in advance!
Upvotes: 0
Views: 382
Reputation: 521513
If the two tables have identical structures, or if there is a subset of columns which could be made to be the same, then a UNION
query might work here:
SELECT *, 0 AS type FROM students WHERE lastname LIKE ?
UNION ALL
SELECT *, 1 FROM staff WHERE lastname LIKE ?
ORDER BY type;
I removed the LIMIT
clause because you don't have an ORDER BY
clause, which makes using LIMIT
fairly meaningless.
Note that I introduced a computed column type
which the result set, when ordered by it, would place students before staff. Then, in your PHP code, you would just need a bit of logic to display the header for students and staff:
$count = mysqli_num_rows($result);
$type = -1;
while ($count > 0) {
$row = mysqli_fetch_array($result, MYSQLI_ASSOC);
$curr_type = $row["type"];
if ($type == -1) {
echo "<h1>Students:</h1>";
$type = 0;
}
else if ($type == 0 && $curr_type == 1) {
echo "<h1>Staff:</h1>";
$type = 1;
}
$name = $row["lastname"];
echo "<p>$name</p>";
--$count;
}
Upvotes: 2