My search script is finding address rows that it shouldn't - php

I have a search engine that searches addresses. It works as designed but I've run across an issue that I can't figure out a work around for.
Currently if I search for "23 Main St" and let's say Main street is in the 87232 zip code. This search will display every address that's on Main street because the street number I'm searching for has "23" with is also in the 87232 zip code.
I'm wondering if there is a way to program it to accept the space behind the "23 " and that would rule out the zip code? Or maybe you guys have a more thought out solution?
Here is my query code. It uses ajax live search:
if($_POST['query'] != '') {
$pieces = explode(" ", $_POST['query']);
$index = 0;
$substring = "";
while ($index < count($pieces)) {
$substring .=" CONCAT(Name,Address,City,State,Zip) like '%" . $pieces[$index] . "%'" ;
if ($index !=count($pieces)-1){
$substring .= " and ";
}
$index++;
}
$query = "SELECT * FROM database where ";
$query .= $substring;
$query .= ' ORDER BY Name ASC, dt DESC ';
}

Related

How can I write a query to select similar titles?

I would like to select those movies which have similar titles.
I found this, but this way it dosn't work, it gives nothing. I would like to give toy story 2, toy story 3 and others with similar title like toy soldielrs, etc.
$title = "Toy Story";
$query = mysql_query("SELECT title, year, poster, LEVENSHTEIN_RATIO( ".$title.", title ) as textDiff FROM movies HAVING textDiff > 60");
I can compare strings in PHP with this function:
static public function string_compare($str_a, $str_b)
{
$length = strlen($str_a);
$length_b = strlen($str_b);
$i = 0;
$segmentcount = 0;
$segmentsinfo = array();
$segment = '';
while ($i < $length)
{
$char = substr($str_a, $i, 1);
if (strpos($str_b, $char) !== FALSE)
{
$segment = $segment.$char;
if (strpos($str_b, $segment) !== FALSE)
{
$segmentpos_a = $i - strlen($segment) + 1;
$segmentpos_b = strpos($str_b, $segment);
$positiondiff = abs($segmentpos_a - $segmentpos_b);
$posfactor = ($length - $positiondiff) / $length_b;
$lengthfactor = strlen($segment)/$length;
$segmentsinfo[$segmentcount] = array( 'segment' => $segment, 'score' => ($posfactor * $lengthfactor));
}
else
{
$segment = '';
$i--;
$segmentcount++;
}
}
else
{
$segment = '';
$segmentcount++;
}
$i++;
}
// PHP 5.3 lambda in array_map
$totalscore = array_sum(array_map(function($v) { return $v['score']; }, $segmentsinfo));
return $totalscore;
}
But how can I compare in a SELECT query or any other way?
You can use like queries for that:
Following example will return all the records from table customer for which customer name ends with kh
select * from customer where name like '%kh'
Following example will return all the records from table customer for which customer name start with kh
select * from customer where name like 'kh%'
Following example will return all the records from table customer for which the middle world of customer name is kh
select * from customer where name like 'kh%'
if you want more specific record then add some and/or condition in your query
I recommend you to read this
http://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html#operator_like
I think you might need to define how similar things need to be to be considered a match.
But if you just wanna search for containing words, you could split your search string by whitespaces and use it in a REGEXP in your query
$search_array = explode(" ", "Toy story");
$query = "SELECT title, year, poster FROM movies WHERE title REGEXP '".implode("|", $search_array)."'";
This would probably match a lot rows, but you could make a more restrictive regular expression.

count some limited words and display them correspond to their names

I am using a search box that searches the user input from "title". Besides this i want to count some keywords from another column "subject" only in the presense of user input corresponds in "title" column. but the problem is that how to find count of only words i have mentioned in the query i.e.
Title Subject
a word1,word2,word1,
ab word2,word4,word3,
bb word1,word4,word4,
aa word2,word2,word4,
cb word1,word1,word3,
ac word2,word1,word3,
So, here if i have searched for a in textbox then, how can i get count of word1 from subject where only a is present in the title field and then similar for the other words so that i could get output like:
your search a contains :
word1 (3)
word2 (5)
word3 (2)
word4 (2)
The code for query is given below:
$getq = "SELECT Title,Subject COUNT(*) FROM tablename WHERE Title LIKE '%$search_each%' Subject LIKE '%word1%' OR Subject LIKE '%word2%' OR Subject LIKE '%word3%' OR Subject LIKE '%word4%') GROUP BY Subject";
$getquery = $conn->query($getq);
while( $runrows = mysqli_fetch_assoc($getquery))
{
$sub = $runrows ['Subject'];
$countsub = $runrows ['COUNT(*)'];
}
echo "<a href='#'>"word1"(".$countsub.")</a> ";
echo "<a href='#'>"word2"(".$countsub.")</a> ";
echo "<a href='#'>"word3"(".$countsub.")</a> ";
echo "<a href='#'>"word4"(".$countsub.")</a> ";
Here, $search_each is textbox input and the above code shows nothing in place of $countsub because i don't know how to get individual count for all words under presense of user's search term. How this can be done?.
Your help will be highly appreciated.
Try this:
$z = array("word1", "word2", "word3", "word4", "word5");
$countsub1 = array();
for ($i = 0; $i <= 4; $i++) {
$getq3 = "SELECT COUNT(*) FROM table WHERE (Subject LIKE '%$z[$i]%' AND Title LIKE '%$search_each%') ";
$getquery4 = $conn->query($getq3);
while ($runrows = mysqli_fetch_assoc($getquery4)) {
$sub = $runrows['Subject'];
$countsub = $runrows['COUNT(*)'];
}
$countsub1[$i] = $countsub;
echo "<a href='#' >$z[$i](" . $countsub1[$i] . ")</a><br> ";
}
Don't write links outside the loop, this can solve your problem.

PHP and mysql Ignoring the special chracters present in the database

a little help on this one, here are its details
[Products]
id int
name text
category
color
Problem is the values of the color field, sample values are:
GOLDRED
GOLD-RED
GOLD/RED
BLUE/GREEN-RED
WHITE GOLD-YELLOW/ORANGE
I could very much clean the search query such as this sample using a basic function
"select * from products where color=".cleanstring($stringval)." limit 1";
function cleanstring($var) {
$newtext = $var;
$newtext = preg_replace("/[^a-zA-Z0-9\s]/", "", $newtext);
$newtext = str_replace(" ", "", $newtext);
$newtext = strtoupper($newtext);
return $newtext;
}
The problem is with the content. It's thousands of records without any form of standard in using a naming convention.
I want to select those records with its values clean similar to my cleanstring().
Example:
Query = GOLDRED
Can select
GOLD-RED
GOLD RED
GOLDRED
GOLD/RED
GOLDRED
Any solution that you could recommend? Code is in PHP/MySQL.
"select * from products where 1".cleanstring($stringval);
function cleanstring($var) {
$color_list = array('GOLD','RED','GREEN','WHITE');
$sql_where='';
foreach( $color_list AS $v){
if(strpos($var, $v)!==false){
$sql_where .=" AND color LIKE '%{$v}%'";
}
}
return $sql_where;
}
//select * from products where 1 OR color LIKE '%GOLD%' OR color LIKE '%RED%'
REMARK:
input: GOLDRED ,
match: GOLD RED,GOLD-RED,GOLD/RED..... GOLD/RED/ABC,RED_GOLDGREEN,
may be after get all data , then make func ranking by match % ,like search engine
Probably You could make just a MySQL regexp with 'GOLD.?RED' or 'GOLD(-|[[:space:]])?RED' ?
That's an online example I made : http://regexr.com?34mmg
Not the best way, and I am sure has tons of downfalls, but if I did not make any mistakes in php code (don't have machine to try it out), it would do the work:
"select * from products where color REGEXP '".cleanstring($stringval)."' limit 1";
function cleanstring($var) {
$var = preg_replace('![-\/ ]+!', '', $var);
$strLength = strlen($var);
$parts = array();
for ($i = 1; $i <= $strLength; i++) {
$parts[] = ($i > 0) ? substr($var, 0, $i).'[-/ ]?'.substr($var, $i);
}
return "[[:<:]](".implode('|', $parts).")[[:>:]]";
}
It would output something like this:
"select * from products where color REGEXP '[[:<:]](G[-/ ]?OLDRED|GO[-/ ]?LDRED|GOL[-/ ]?DRED|GOLD[-/ ]?RED|GOLDR[-/ ]?ED|GOLDRE[-/ ]?D)[[:>:]]' limit 1"
which basically breaks your keyword in pieces letter by letter, i.e.
G OLDRED
GO LDRED
GOL DRED
GOLD RED
GOLDR ED
GOLDRE D
and do the "LIKE" statement on them but with smarter word boundaries and instead of just space, it considers "-" and "/" as well.

Preg_match with different combinations of words

I've a littile question about preg_matches, these regex things are really hard to understand and I hope someone can give the right awnser!
I have the following text:
0A-24-423
But this can also be:
0A-242-2
or
0A-2-423
How can I use preg_matches to filter these? I was using
substr($something, 0,2)
so that it captures 0A and
substr($seat, 4,5)
This will capture 24 but when you get 242 it wont capture the last 2....
Hope someone can help creating this in preg_match!
to make it more clear what I have now:
foreach($_POST['seats'] AS $seat) {
if ($count > 0) {
$selectQuery .= " || ";
}
$selectQuery .= " ( rowId = '" . substr($seat, 0,2) . "'";
$selectQuery .= " and `order` = " . substr($seat, 3,5) . " ";
$selectQuery .= " and columnId = " . substr($seat, 6) . " ) ";
$count++;
and $seat had the following format XXXXXX and using substr I can get the right things (for example: 0J3017)
Something Like this should do it:
$selectQuery = "SELECT * from seats where ";
$count = 0;
$pattern = "I DON'T KNOW :( ";
foreach($_POST['seats'] AS $seat) {
if ($count > 0) {
$selectQuery .= " || ";
}
preg_match($pattern, $seats, $matches);
$selectQuery .= " ( rowId = '" . $matches[0] . "'";
$selectQuery .= " and `order` = " . $matches[1] . " ";
$selectQuery .= " and columnId = " . $matches[2] . " ) ";
$count++;
and $seats is explained in the beginning of the post (it has a format of XX-XXX-XXX
where the first 2 XX are 0[A-Z] (yes the 0 is correct)
where the 3 first XXX are [0-9]
Where the last 3 XXX are [0-9]
EDIT:
there are 2 ways to solve this.
Option 1:
$pattern = "/(.*)-(.*)-(.*)/";
or use explode() function.
It does not look like you need to be using regular expressions. Here's an example using explode() and list():
list($row_id, $order, $column_id) = explode('-', $seat, 3);
You could then use those three new variables in your $selectQuery.
EDIT : Since the OP has stated his requirement as a comment to my answer I have updated my answer accordingly.
You can try this:
$pattern = "/[A-Z\d]{1,2}-[A-Z\d]{1,3}-[A-Z\d]{1,3}/";
$matched = preg_match($pattern, $something);
if ($matched === 0) {
die('regex did not match');
}
$matched will give you 1 for a matched string and 0 if not matched.

Cannot insert sentence to database

I have some sentences. I have to choose the sentences that consist of more than 6 words. and then they will be inserted to database.
<?php
require_once 'conf/conf.php';
$text = " Poetry. Do you read poetry while flying? Many people find it relaxing to read on long flights. Poetry can be divided into several genres, or categories. ";
$sentences = explode(".", $text);
foreach ($sentences as $sentence) {
if (count(preg_split('/\s+/', $sentence)) > 6) {
$save = $sentence. ".";
$sql = mysql_query("INSERT INTO tb_name VALUES('','$save')");
}
}
?>
The result is only the second sentence that inserted in database => 'Do you read poetry while flying? Many people find it relaxing to read on long flights'. whereas the third sentence also should be inserted. please help me, thank you : )
Here is the solution you're looking for. You cannot add multiple rows since your ID value is left unspecified and it is the key into the table. Since you want to add the sentences to the same row, you need to execute one query.
$text = " Poetry. Do you read poetry while flying? Many people find it relaxing to read on long flights. Poetry can be divided into several genres, or categories. ";
$sentences = explode(".", $text); $save = array();
foreach ($sentences as $sentence) {
if (count(preg_split('/\s+/', $sentence)) > 6) {
$save[] = $sentence. ".";
}
}
if( count( $save) > 0) {
$sql = mysql_query("INSERT INTO tb_name VALUES('','" . implode( ' ', $save) . "')");
}
Now, both sentences will be inserted into the same row in the database, separated by a space. You can change what they're separated by if you modify the first parameter to implode().
The query that gets generated is this:
INSERT INTO tb_name VALUES('',' Do you read poetry while flying? Many people find it relaxing to read on long flights. Poetry can be divided into several genres, or categories.')
Replace:
$sentences = explode(".", $text);
with this:
$newSentences = array();
$sentences = preg_split("/(\.|\?|\!)/", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
$odd = false;
foreach($sentences as $sentence) {
$sentence = trim($sentence);
if($sentence != '') {
if(!$odd) {
$newSentences[] = $sentence;
} else {
$newSentences[count($newSentences) - 1] .= $sentence;
}
$odd = !$odd;
}
}
It separates sentences ending in with . or ? or !. The foreach just reassembles the sentences.
Example here: http://codepad.org/kk3PsVGP

Categories