Narrow search results from mysql database keywords - mysql

I have a large database containing part numbers for a filter company. Several of the products have similar years and model numbers. I have a php script that is searching a text keyword section for each part.
So for a 1997-1999 Honda Crf 250 090987 19.95 the keywords are:
1997 1998 1999 honda crf 250 090987
I got the code from a tutorial and it's written to search the keywords section for everything separated by a space. The problem is that a lot of the listings have honda or similar year spreads.
I need to figure out how to alter the php to narrow the results so if someone types "1997 honda", all of the hondas and '97s don't show up but only ones that are 1997 hondas.
I'm new to php and I've looked all around and can't figure it out. Any help will be thoroughly appreciated.
here's the php:
$keywords = $_GET['keywords'];
$terms = explode(" ", $keywords);
$query = "SELECT * FROM search WHERE ";
foreach ($terms as $each){
$i++;
if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
// connect
mysql_connect("localhost", "root", "root");
mysql_select_db("catalog");
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while ($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$year = $row['year'];
$manufacturer = $row['manufacturer'];
$product = $row['product'];
$partnumber = $row['partnumber'];
$price = $row['price'];
echo "<div id=\"results\">
<div class=\"words\">$year</div><div class=\"words\">$manufacturer</div><div class=\"words\">$product</div><div class=\"words\">$partnumber</div>$price<br /></div>";
}
}
else
echo "<div class=\"no_results\"><center>No results found for \"<b>$keywords</b>\"</center></div>";
// disconnect
mysql_close();
?>

Interesting problem.
I thought of 2 approaches:
(1) if you have control over the database structure, you could SELECT WHERE (make = 'Honda' AND Year IN (1997,1998,1999)) AND the "like" stuff you already have (without the make/year). But you would need to separate out the model years and make into separate fields.
(2) otherwise, if we can assume the input is always "year(s) make [other keywords], we could do what izuriel suggested while I was typing this, just "AND 'keywords = '1997' AND keywords = 'honda' AND (our existing list of "like" clauses)".
that way you'd get only 1997 Hondas that have any or all of the other keywords.

Use AND in the query instead of OR to enforce that all keywords must match, otherwise one keyword match will return a result always. Outside of that, you'll have to do some Relevance work in code which might slow down the application.

I recommend you to use one symbol percentage at the end of the word and you and instead of or and you limit in your query if the database is large

Related

Loop in column name MYSQL

I am using MYSQL.My table contains column name as Revenue2000,Revenue2001,Revenue2002,....,Revenue 2016,Revenue 2017
Traditional way(to select all column manually):
select Revenue2005,
Revenue2006,
Revenue2007,
Revenue2008,
Revenue2009,
Revenue2010
from table_name
Desired Way:
I want to write a Dynamic select statement .There should 2 variables "start" and "end" so that i can make it dynamic.User has the option to specify the starting year and ending year and can view the desired result.
In above case, Start year =2005
End Year=2010
Yes, it's bad database design, and the best answer would be "don't do this at all, just fix your table." Unfortunately, sometimes you're stuck with something someone else made, and can't change it for whatever reason, but you still need to accomplish something (welcome to my life). I would do it like this:
Get the years from user input and convert them to integers in case someone enters something silly/naughty. Don't depend on client-side validation. Prepared statements won't help you here because these will be used as parts of column names.
$start = (int) $_POST['start'];
$end = (int) $_POST['end'];
Do a quick sanity check to make sure that the range makes sense and should work with what's in your database.
if ($start > $end
|| $start < $lowest_year_in_your_db
|| $end > $highest_year_in_your_db) {
// quit with error
}
Then you can generate a list of columns to use in your query. Here's one way with range and array_map, but you could also just build a string with a for loop.
$columns = implode(', ', array_map(function($year) {
return "Revenue$year";
}, range($start, $end)));
$sql = "SELECT $columns FROM table_name";
Theoretically, the worst thing that should be able to happen with this is that you'd get a column that didn't exist, and your query would fail.
But really, if you have any choice about it, don't do this. Normalize your database as people have stated in the comments, or find whoever keeps adding more year columns to the database and make them do it.
As already pointed out the database design is horrible. You should really normalize it, it's worth the effort.
However if that is not possible at the moment the follow code should do exactly what you need:
// Connect to DB
$mysqli = new mysqli("localhost", "USERNAME", "PASSWORD", "DATABASE");
// Get column names
$columns = $mysqli->query('SHOW COLUMNS FROM revenue')->fetch_all();
$columnNames = array_column($columns, 0);
// Extract years from column names
$years = array_map(function($columnName) {
return (int) substr($columnName, -4);
}, $columnNames);
// Get max and min year
$maxYear = max($years);
$minYear = min($years);
// Input year start and end
$start = (int) $_POST['start']; // User-input
$end = (int) $_POST['end']; // User-input
// Avoid wrong inputs
if($start > $end || $start < $minYear || $end > $maxYear) {
die('Error');
}
// Create the SQL-query
$selectColumns = [];
for ($i = $start; $i <= $end; $i++) {
$selectColumns[] = "revenue" . $i;
}
$queryString = "SELECT " . implode(", ", $selectColumns) . " FROM TABLE";
// Run the query
// ...

MySQL / PHP: cannot perform two separate queries on same database?

I have one database with two tables: "music" and "agenda".
But for some reason once I have queried one table, I cannot perform a similar query on the other table. Or in any case, its variables are empty.
I'd think I could just keep the connection open and perform a second query after the first "while". Like so:
<?php
mysql_connect('localhost', 'root', 'root');
mysql_select_db('erikverwey');
$result = mysql_query("SELECT * FROM agenda ORDER BY date DESC LIMIT 0, 2") or die(mysql_error());
while($row = mysql_fetch_array($result)) {
$count++;
$date[$count] = $row['date'];
$time[$count] = $row['time'];
$place[$count] = $row['place'];
$venue[$count] = $row['venue'];
$who[$count] = $row['who'];
$concert[$count] = $row['concert'];
$urlvenue[$count] = $row['urlvenue'];
}
$result2 = mysql_query("SELECT * FROM music ORDER BY id LIMIT 0, 5") or die(mysql_error());
while($row = mysql_fetch_array($result2)) {
$count++;
$song[$count] = $row['song'];
$artist[$count] = $row['artist'];
$duration[$count] = $row['duration'];
$url[$count] = $row['url'];
}
mysql_close();
?>
But no. In this case, all the variables from the table "music" remain empty.
I've been looking for an answer, but no luck. I'm still new to MySQL, though, so apologies beforehand if this is standard stuff. Thanks!
I found the glitch. Because the counter "$count" was used a second time, it started where it left off and couldn't find any data.
Use a different counter, also in the variables (!), and all is good.

Drupal 6 : Not able to fetch group_id(gid) from OG table

I am creating nodes pro-grammatically by fetching emails. Where I am splitting the subject of the mail for creating it for specific group & the title of the node.
Now I want to fetch the group_id by the description of the group and wrote query for it, but it's not working. Let me paste the code here..
list($group_name, $title_text) = explode(', ', $title);
$query = "SELECT * FROM {og} WHERE og_description = ' ".$group_name." ' ";
$group_details = db_query($query);
while ($group = db_fetch_object($group_details)) {
$gid = $group->nid;
}
echo $gid;
echo $gid is giving nothing. Though $group_name = 'Logo design' & gid = 1442 for it in table.
Is there anything I am missing here ?
Check out the following two pages , the examples give here does not use the single quotes around the placeholder in the query ($group_name - in your example) .
http://drupal.org/node/310072
One of the lines says "Note that placeholders should not be escaped or quoted regardless of their type" .
http://drupal.org/node/1407528
I have solved it. Here is the answer:-
$title = "ED's presentation, This content is for ed's presenation"; //This is the subject of the mail, which I am fetching.
list($group_name, $title_text) = explode(', ', $title);
$query = "SELECT nid FROM {og} WHERE og_description = '".$group_name."'";
$group_details = db_query($query);
while ($group = db_fetch_object($group_details)) {
{
$gid = $group->nid;
}
Thanks :)

autocomplete slow with large database search

I've spent a considerable amount of time trying to track this one down. I've used a boxed autocomplete on my site (http://www.devbridge.com/projects/autocomplete/jquery/). As you type the word, it sends it as a GET variable to a page for processing where it is searched for in a mySQL database. The page looks like this:
$get = $_GET['query'];
$query = "SELECT title,author,id,isbn10,isbn13 FROM textbook
WHERE title LIKE '" . $get . "%'
OR author LIKE '" . $get . "%'
LIMIT 5
";
$result = mysql_query($query,$connection);
$resString = "";
$idString = "";
while($data = mysql_fetch_array($result)){
$resString .= "'" . title($data['title']) . " by " . $data['author'] . "',";
$idString .= "'" . $data['id'] . "',";
}
$resString = rtrim($resString, ',');
$idString = rtrim($idString, ',');
$code = "{\n";
$code .= "query:'" . $get . "',\n";
$code .= "suggestions:[" . $resString . "],\n";
$code .= "data:[" . $idString . "]\n";
$code .= "}";
echo $code;
This outputs a basic JSON dataset that is read and shot back as a result. The problem is that it has been REALLY slow. the "LIMIT 5" helped a ton to speed it up some. However, still running slow after the initial result set shows. I may type in "hum" and it will come back with a quick result set, but any letters/words after that take 4-6 seconds to show. The database is 300K records roughly. Attached is a picture of my database structure page:
database http://semesterkey.com/images/data.jpg
Im just trying to figure out how to speed things up. I think it might be my database structure, it could be how Im querying? I just have no idea. Thanks in advance for your help!
There is only solution is that use Indexing on column which you want to show in autocomplete in your Database, hope this will help you
Yes, the answer to your problem is an index on the (author, title) group of columns. It will grow the amount of space used by the DB and will decrease the performance on INSERT, UPDATE, DELETE in that table, but it will increase the interrogation performance.
make index on author and title may help you to improve the performance.
Syntax help for those who don't grasp which above answer
ALTER TABLEYour_table_nameADD INDEX (column_title) ;

PHP Array Duplicates

my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
What I would like to do is display each user individually, and count the number of contacts each user has. I had a look at the post "How to detect duplicate posts in PHP array, which helped a bit, but I am still stuck.
Please see my code for the query below, I have left out the array duplicate part as it is a pretty mess at the moment.
<?php
$result = mysql_query("SELECT * FROM vines");
while($row = mysql_fetch_array($result)) {
$results=$row['vinename'];
echo $results;
echo "<br />";
}
?>
This result returns the below, obviously these are records from the vinename coloumn.
Marks Vine<br />
Marks Vine<br />
Marks Vine<br />
Tasch Vine<br />
Tasch Vine<br />
Regards
Mark Loxton
Hi there, my first post here and hoping someone can help. I am querying a table in a mySQL DB, and obviously getting the results. However, the table is used to store multiple entry by one user for the purpose of user contacts.
You can do this in the query itself a lot more easily than in the PHP code afterwards.
SELECT name, COUNT(id) AS count FROM vines GROUP BY name
Just change the SQL Query to
SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename
and then do
echo $row['vinename']." #".$row['counter']."<br />";
I would run two types queries...
1) Select each UNIQUE user from vines.
2) For each user in that set, run a second COUNT query against that user's id in the table "vines".
I hope that helps.
You can create a separate array to store records you've already output there.
<?php
$result = mysql_query("SELECT * FROM vines");
$duplicates = array(); ## store duplcated names here
while($row = mysql_fetch_array($result)) {
$results = $row['vinename'];
if (!array_key_exists($results, $duplicates)) {
echo $results;
echo "<br />";
$duplicates[$results] = 1; ## mark that we've already output this records
}
}
?>
You can try, change your query to use count and group of SQL.
Somoe thing like
$result = mysql_query("SELECT count(*) as total,name FROM vines GROUP by name");
firstly thank you everyone for such awesome input. I seriously did not expect such a quick response. I am seriously grateful.
I used the recommendation from Jitter. I have pretty much been going through so many variations of the above code today, but just needed that missing piece.
Thanks, everyone. Below is what the final code looks like for anyone else who has the same problem in the future.
<?php
$result = mysql_query("SELECT vinename, COUNT(vinename) as counter FROM vines GROUP BY vinename ORDER BY counter DESC LIMIT 0, 3");
while($vinerow = mysql_fetch_array($result))
echo $vinerow['vinename']." has ".$vinerow['counter']." tomatos."."<br />";
?>
change your query to:
SELECT distinct * FROM vines