PHP SQL Multiple autocomplete search - php

currently I've written a code and it works fine with only keyword. Also, it doesn't take care of multiple entries. for example, if I have the keyword "blue" twice in DB; it shows "blue" twice in the search input box when I start typing "blue". Rest of the code works fine. How should I tweak my code? Also, if a column has "blue" & "green" as the row; it shows the complete thing: "blue & green". My php code:
<?php
$keyword = mysql_real_escape_string($_POST['keywords']);
$sql = "SELECT * FROM job WHERE work='$keyword' or work LIKE 'ANOTHER_PARAMETER' LIMIT 5";
$result = mysql_query($sql);
$numrows = mysql_num_rows($result);
echo //details and run the loop
?>

You can try modifying your SQL DB. You can have a column of "work_ids" and another for "work corresponding to those ids".
Sorry, I left a part of your question unanswered but thanks to #T-shirt Dude; I remebered it instantly. If I am reading your question right, you want to search for multiple keywords in a single column? If so you can do:
$sql = mysql_query("SELECT work_id, work FROM job
WHERE work like '%$q%' OR work like 'ANOTHER_PARAMETER'
ORDER BY work_id LIMIT 10");
You can put as many "OR"s that you want.

Considering the work to be the column with the values 'blue' and 'green' in it, the code should be:
"SELECT * FROM job WHERE work='$keyword' or work LIKE 'ANOTHER_PARAMETER' GROUP BY work LIMIT 5";
If that's not the case, I was unable to understand your question.

I'm not sure I completely follow--seeing the code that creates response might help us a little more.
At any rate, from the way I'm understanding your problem, it sounds like you might need a group by.

Related

Reversing the order of displayed data from a SELECT query

My website (thanks to help from many of you here on SO) is set up to display a fixed number of updates (52) where each Friday, one rotates out, and a new one rotates in. The 52 updates are displayed 4 per page across 13 pages. It works perfectly.
However, the new update appears at the END of the displayed updates. I would like the new update to be the first one people will see.
Here is my query:
$conn = dbConnect('query');
$updates = "SELECT update_id, update_title, update_desc, path
FROM updates
WHERE flag_live = ?
ORDER BY update_id DESC
LIMIT ?, ?";
$stmt = $conn->prepare($updates);
$stmt->bind_param('sii', $uLive, $offset, $limit);
$stmt->bind_result($uId, $uTitle, $uDesc, $uPath);
$stmt->execute();
$stmt->store_result();
$stmt->fetch();
I want the items to display in reverse order as they currently do. If I change the ORDER BY from DESC to ASC it picks a different set of data which I do not want. Thus, from my research I have seen that either array_reverse() or rsort would do the trick. I need to know what syntax is correct to use array_reverse() properly here.
I don't get along well with PHP, but something like this?
$results = $stmt->fetchAll();
$results = array_reverse( $results );
foreach ($results as $row)
{
/* $row will contain each row in the reversed array one at a time. do your usual process-one-row logic here */
}
Btw, when you don't know what a PHP function returns when you call it, there is a very useful debugging function, var_dump. You can call it on anything and it'll print what it's composed of, recursively.
http://au1.php.net/manual/en/function.var-dump.php
Maybe try something like this:
$results = $stmt->fetchAll();
$results = array_reverse( $results );
The next part can be done a few different ways so it really depends on how you are going to use the results and paginate them.
You could use a for loop: http://us3.php.net/manual/en/control-structures.for.php
Or foreach: http://us3.php.net/manual/en/control-structures.foreach.php
Okay, after a lot of headbanging, I was able to accomplish this task, though not in a manner that I had considered when I posted this question. What I ended up doing was writing a subquery which allowed me to reverse the order of the updates displayed on each page, and as you'll know, this only reverses the order of the four updates visible on the page, NOT the overall order of the 52 chosen (see original question).
The next step was to 'reverse' my pagination system...no small task...rewriting logic, testing code, etc. So by reversing things with a subquery and reversing my pagination, I achieved my goal.
All of your suggestions her helped with the final outcome, though not in a way expected. I apologize in advance if this is not as concise as answering my own question should be.

Names for PHP query results and PHP loops.

This might be a simple question, but I can't find a definitive answer I can understand. I use PHP loops alot, I'm fairly new to PHP so they are usually simple like so:
<?php
$result = mssql_query("SELECT Price FROM Window_Extras WHERE ExtraID = '4' ");
while ($row = mssql_fetch_array($result)) {
?>
<a title="<?php echo $row['Colour']; ?>"></a>
<?php }?>
Is a really simple example, that doesn't make much sense, but I hope it shows how I use them. The question I wanted to ask was if $row and $result have to be named that for it to work, could they for example be named $priceresult and $pricerow?
This is because sometimes I would like to use multiple queries for a single loop, for example:
<?php
$result = mssql_query("SELECT Price FROM Extras WHERE ExtraID = '4' ");
$colourresult = mssql_query("SELECT ColourID FROM Colours WHERE Type = '8' ");
while ($row = mssql_fetch_array($result, $colourresult)) {
?>
This however didn't work, when I tried to echo out:
<?php echo $row['ColourID']; ?>
Can anyone tell me how I should be approaching this, and if I am at all on the correct track. Sorry if I havn't explained it very well.
To answer your first question:
Yes, you can use any variable name you like for the result and row variables. PHP doesn't care what you call them, and in fact it's perfectly possible to have several of them in use at any given time, in which case they obviously need to have different names.
You then followed up that question by asking why the following code doesn't work:
$result = mssql_query("SELECT Price FROM Extras WHERE ExtraID = '4' ");
$colourresult = mssql_query("SELECT ColourID FROM Colours WHERE Type = '8' ");
while ($row = mssql_fetch_array($result, $colourresult)) {
....
}
The reason for this is that the _fetch_array() function can only work with one set of results at a time. You would need to fetch a separate row array for each of them.
It's not clear what you're trying to do with these two queries, and why you would want to put them into the same loop together in the way you've shown.
I'm going to assume that the two queries are linked in some way that makes it logical for you to use them together like this? Perhaps the Extra item you're loading has a known Colour; ie you know that the Extra item numbered 4 is coloured with the Colour numbered 8?
Typically a program wouldn't be written with this knowledge; it would be part of the data. So in the Extras table, you would have a ColourID field, which would contain the value 8. The program would load the Extras record, see that the ColourID was set, and then load the matching Colours record according to what it saw.
Thus, your code could look something like this:
$result = mssql_query("SELECT Price FROM Extras WHERE ExtraID = '4' ");
while ($row = mssql_fetch_array($result)) {
$colourresult = mssql_query("SELECT ColourID FROM Colours WHERE Type = '".$row['colourID']."' ");
while ($row2 = mssql_fetch_array($result)) {
....
}
}
Inside the inner while loop, you could then access fields from either query, using $row or $row2 respectively (again, you can name these as you see fit).
However, that's not the end of the story, because SQL actually has the ability to merge these two queries into one without needing all that PHP code, using a thing call a SQL JOIN.
Now we can write a more complex query, but go back to having simpler PHP code:
$result = mssql_query("SELECT Extras.Price, Colours.ColourName FROM Extras WHERE ExtraID = '4' INNER JOIN Colours ON Colours.ColourID = Extras.ColourID");
while ($row = mssql_fetch_array($result)) {
....
}
If you're a beginner in PHP and SQL, these concepts are all probably new to you, so I advise trying them out, experimenting with them, and most importantly, reading a few (good quality) tutorials about them before proceeding much further.
Hope that helps. :)
(PS: as I said above, make sure you're reading good tutorials; beware of bad PHP examples and teaching sites -- there's a lot of them out there, teaching poor code and obsolete techniques; make sure you're reading something worthwhile. A good place to start might be http://phpmaster.com/)
This is because mssql_fetch_array can only take one result set. So removing $result and leaving $colourresult should work for you.
See: http://php.net/manual/en/function.mssql-fetch-array.php
Your variables ($...) can be called whatever you want, it's generally better to name them in a way that you can understand, hence most of the examples in the PHP Manual contain variables like $row, $result, $query, etc.
In terms of your database query, you can only pass one query to the mssql_query method. If you have data from different tables that you need to display, you should try and join the tables if possible using SQL rather than looping through multiple result sets.

Extremely slow search page load (MySQL and PHP)

I made a simple search box on a page, where a user can type in keywords to look for photos of certain items, using PHP. I'm using an MySQL database. I trim the result and show only 10 to make the loading quicker, but certain set of keywords causes the browser to hang on both IE and Firefox. When this happens on IE, I can see outlines of photos (just the silhouette) beyond the 10 results with an "X" mark at the top right corner, similar to when you load a photo and the photo doesn't exist on a webpage, even though I wrote the code to show only 10 results. The database has over 10,000 entries, and I'm thinking maybe it's trying to display the entire set of photos in the database. Here are some code that I'm using.
I'm using the function below to create the query. $keyword is an array of the keywords that the user has typed in.
function create_multiword_query($keywords) {
// Creates multi-word text search query
$q = 'SELECT * FROM catalog WHERE ';
$num = 0;
foreach($keywords as $val) { // Multi-word search
$num++;
if ($num == 1) {
$q = $q . "name LIKE '%$val%'"; }
else {
$q = $q . " AND name LIKE '%$val%'";}
}
$q = $q . ' ORDER BY name';
return $q;
//$q = "SELECT * FROM catalog WHERE name LIKE \"%$trimmed%\" ORDER BY name";
}
And display the result. MAX_DISPLAY_NUM is 10.
$num = 0;
while (($row = mysqli_fetch_assoc($r)) && ($num < MAX_DISPLAY_NUM)) { // add max search result!
$num++;
print_images($row['img_url'], '/_', '.jpg'); // just prints photos
}
I'm very much a novice with PHP, but I can't seem to find anything wrong with my code. Maybe the way I wrote these algorithms are not quite right for PHP or MySQL? Can you guys help me out with this? I can post more code as necessary. TIA!!
Don't limit your search results in PHP, limit them in the SQL query with the LIMIT keyword.
As in:
select * form yourtable where ... order by ... limit 10;
BTW, those LIKE '%something%' can be expensive. Maybe you should look at Full text indexing and searching.
If you want to show a More... link or something like that, one way of doing it would be to limit your query to 11 and only show the first ten.
Apart from the LIMIT in your query, I would check out mysql full text search (if your tables have the MyISAM format).
Why don't use use MySQL to limit the number of search results returned?
http://dev.mysql.com/doc/refman/5.0/en/select.html
add LIMIT to your query.
you are retrieving all rows from DB (lot of bytes traveling from DB to server) and then you are filtering the first 10 rows.
try
$q = $q . ' ORDER BY name LIMIT 10';
LIKE is slow also according to Flickr(slides 24-26). You should first try to use FULL TEXT indexes instead. If your site still seems slow there are also some other really fast(er)/popular alternatives available:
sphinx
elasticsearch
solr
The only thing that is a little bit annoying that you need to learn/install these technologies, but are well worth the investment when needed.

debugging a mysql insert fail in php

I'm having problems debugging a failing mysql 5.1 insert under PHP 5.3.4. I can't seem to see anything in the mysql error log or php error logs.
Based on a Yahoo presentation on efficient pagination, I was adding order numbers to posters on my site (order rank, not order sales).
I wrote a quick test app and asked it to create the order numbers on one category. There are 32,233 rows in that category and each and very time I run it I get 23,304 rows updated. Each and every time. I've increased memory usage, I've put ini setting in the script, I've run it from the PHP CLI and PHP-FPM. Each time it doesn't get past 23,304 rows updated.
Here's my script, which I've added massive timeouts to.
include 'common.inc'; //database connection stuff
ini_set("memory_limit","300M");
ini_set("max_execution_time","3600");
ini_set('mysql.connect_timeout','3600');
ini_set('mysql.trace_mode','On');
ini_set('max_input_time','3600');
$sql1="SELECT apcatnum FROM poster_categories_inno LIMIT 1";
$result1 = mysql_query($sql1);
while ($cats = mysql_fetch_array ($result1)) {
$sql2="SELECT poster_data_inno.apnumber,poster_data_inno.aptitle FROM poster_prodcat_inno, poster_data_inno WHERE poster_prodcat_inno.apcatnum ='$cats[apcatnum]' AND poster_data_inno.apnumber = poster_prodcat_inno.apnumber ORDER BY aptitle ASC";
$result2 = mysql_query($sql2);
$ordernum=1;
while ($order = mysql_fetch_array ($result2)) {
$sql3="UPDATE poster_prodcat_inno SET catorder='$ordernum' WHERE apnumber='$order[apnumber]' AND apcatnum='$cats[apcatnum]'";
$result3 = mysql_query($sql3);
$ordernum++;
} // end of 2nd while
}
I'm at a head-scratching loss. Just did a test on a smaller category and only 13,199 out of 17,662 rows were updated. For the two experiments only 72-74% of the rows are getting updated.
I'd say your problem lies with your 2nd query. Have you done an EXPLAIN on it? Because of the ORDER BY clause a filesort will be required. If you don't have appropriate indices that can slow things down further. Try this syntax and sub in a valid integer for your apcatnum variable during testing.
SELECT d.apnumber, d.aptitle
FROM poster_prodcat_inno p JOIN poster_data_inno d
ON poster_data_inno.apnumber = poster_prodcat_inno.apnumber
WHERE p.apcatnum ='{$cats['apcatnum']}'
ORDER BY aptitle ASC;
Secondly, since catorder is just an integer version of the combination of apcatnum and aptitle, it's a denormalization for convenience sake. This isn't necessarily bad, but it does mean that you have to update it every time you add a new title or category. Perhaps it might be better to partition your poster_prodcat_inno table by apcatnum and just do the JOIN with poster_data_inno when you need the actually need the catorder.
Please escape your query input, even if it does come from your own database (quotes and other characters will get you every time). Your SQL statement is incorrect because you're not using the variables correctly, please use hints, such as:
while ($order = mysql_fetch_array($result2)) {
$order = array_filter($order, 'mysql_real_escape_string');
$sql3 = "UPDATE poster_prodcat_inno SET catorder='$ordernum' WHERE apnumber='{$order['apnumber']}' AND apcatnum='{$cats['apcatnum']}'";
}

Can php query the results from a previous query?

In some languages (ColdFusion comes to mind), you can run a query on the result set from a previous query. Is it possible to do something like that in php (with MySQL as the database)?
I sort of want to do:
$rs1 = do_query( "SELECT * FROM animals WHERE type = 'fish'" );
$rs2 = do_query( "SELECT * FROM rs1 WHERE name = 'trout'" );
There is no MySQL function like this for PHP, however there is a more advanced substitute for it.
Edit: For those of you who don't know what a query of queries is, it's exactly this and there's a purpose some people do it like this. Using an AND operator is ****NOT**** the same thing! If I want results where username='animuson' for one part of my script and then want all the results out of that query where status='1', it is not logical for me to run another query using an AND operator, it is much more logical to loop through the previous results in PHP. Stop upvoting things without reading the comments on why they weren't upvoted in the first place, that's just lazy. If you don't have a clue what's being talked about, you shouldn't be upvoting or downvoting in the first place.
Well, you may want to do this without touching the db:
while($t = mysql_fetch_array($rs1)){
if($t[name] == 'trout'){
echo 'This is the one we\'re looking for!';
break;
}
}
In PHP, it would be terribly inefficient. You would have to loop through each row and check that its name was trout. However, is there any reason you can't do
SELECT * FROM `animals` WHERE `type` = 'fish' AND `name` = 'trout'
in SQL? It would be much, much faster.
You can also do something like
select morestuff from (select stuff from table where a = b ) where c = d;
Use the AND keyword?
"SELECT * FROM animals WHERE type = 'fish' and name='trout'"
Also, you can use LINQ for php http://phplinq.codeplex.com/

Categories