Select rows where column text contains value of an array - php

I'm building a search function in php/mysql and I'm looking for the right MySql function. My table sort of looks like this:
id | text
--------------------------------------
1 | I like pony's.
2 | Do you like fish?
3 | We like fishes!
I want to search the column 'text' for one of the exact values of an array, for example:
$search_array = array('fish','dogs','cat','panda');
I'm looking for the right MySql function to return only the second row (with the current array). The array can contain hundreds of values.
I have 6000+ rows, growing everyday with +/- 400. I've tried REGEXP but with a large array, it took about 10 seconds before it returned the corresponding rows.
Please help, I'm fighting with this for almost 3 full days now... Thanks in advance!

If the search array is constant, or changes infrequently, I recommend having another two tables, 'tags' and 'tags-text'.
For example, the row with id 2 in your example contains fish, since fish is in our 'tags' table a new record will be placed in a 'tags-text' table. When you are searching with your array, you can search if one of the array components is in the 'tags-text' table, and join the 'text' table and return the text and id and do whatever you need.
Structure of other tables:
'tags' table
id | tags
--------------------------------------
1 | fish
2 | dogs
3 | cats
'tags-text' table
text-id | tags-id
--------------------------------------
2 | 1
Does this help/make sense

Ok I think I've found the easiest solution: let PHP create the mysql query and solve it with WHERE LIKE.
$search_array = array('fish','dogs','cat','panda');
$string = '';
foreach($search_array as $term) {
$string = $string."text LIKE '%".$term."%' AND ";
}
The result of the foreach loop is:
"text LIKE '%fish%' AND LIKE '%dogs%' AND LIKE '%cat%' AND LIKE '%panda%' AND "
Now lets remove the tail of that string and write the query:
$string = substr($string, 0, -5); // removing " AND " at the end of the string
$query = "SELECT * FROM table WHERE $string";
$results = mysql_query($query);
Thanks for the other answers anyway :)

Ok, maybe you should try mixing mysql and php a bit.
Here is the pseudo-code
select 100-1000 rows at one time from db
use strpos to check each element in your array against the text column
if element found
store it
if 2 elements found break the loop
else
continue

Something like this maybe ...
$search_term = implode(",",$search_array);
SELECT * FROM your_table WHERE text IN ($search_term)";

Related

How to add not existing record and return it with zero value in Mysqli

QUERY:
SELECT month(date_created), count(a.ticket_num)
FROM ticket as a
LEFT JOIN user_management as b on b.engineer_id = a.ticket_engineer
WHERE b.tl_id = 'sample_id'
AND year(date_created) = '2019'
GROUP BY extract(year from date_created), extract(month from date_created)
SAMPLE OUTPUT:
month | ticket_num
----------------------
2 | 12
4 | 24
6 | 78
EXPECTED SAMPLE OUTPUT:
month | ticket_num
----------------------
1 | 0
2 | 12
3 | 0
4 | 24
5 | 0
6 | 78
As you can see the above expected output, i'm trying to place all existing month in the first column and set all the count to zero if not existed in the second column. As of now, i only have the query for sorting the ticket count by month that is existed when the ticket is created.
There are different approaches to this problem. One is pure SQL for example.
But I would say a PHP based solution is simpler. Basically you need to get your data into array, then create a loop that outputs the desired months order, and have a condition that sees whether we have a corresponding row in our array and outputs ether the actual data or a zero accordingly.
The only tricky part is to have such an array that would let us check the data availability. For this we have to index it with month numbers. Not a big deal actually
$sql = "SELECT month(date_created), count(a.ticket_num) ...";
$res = $mysqli($sql);
$data = [];
while($row = mysqli_fetch_row($res)) {
$data[$row[0]] = $row[1];
}
Now $data is an array indexed by the month number. The rest is a primitive loop
foreach (range(1,12) as $month) {
echo $data[$month] ?: 0;
}
On a side note I would like to advertise using PDO as opposed to mysqli for your database interactions as this case clearly displays the superiority of the former. Using PDO we can get the indexed array right away, without an explicit loop, thanks to a special fetch mode:
$sql = "SELECT month(date_created), count(a.ticket_num) ...";
$data = $data = $pdo->query($sql)->fetchAll(PDO::FETCH_KEY_PAIR);
That's all!

using MYSQL count function to get two columns

I am currently using the following query to retrieve data from a database:
SELECT product_Id, COUNT(product_Id) as count
FROM my_sales
GROUP BY product_Id
ORDER BY count DESC
in phpmyadmin it looks like this:
_____________________________________
Product_ID | count
__________________|__________________
12 | 13
13 | 21
14 | 24
The PHP Code im using looks like this:
$res = $connVar->prepare($query); //the query described above
$res->execute();
$res->fetch(PDO::FETCH_ASSOC);
while ( $row = $res->fetch(PDO::FETCH_ASSOC) )
{
$data[] = $row;//return the information from the database as an array
echo $data[0]['product_Id']; //trying to target specific indexes of an associative array :/
echo $data[0]['count'];
}
What really needs to happen is that I can store each row as variables so that I can say, print out in php how much stock is left for a particular product.
Been looking on stackoverflow for around 4 hours now and about to give up. There are a lot of questions available about returning the whole dataset within one variable but thats not what i need.
Any help?

SEARCH PHP and MYSQL

I need mysql code or php to handle some search query
Lets say we have these 5 items in our store.
ID | TYPE | Pattern
1. | Kilner | scissor
2. | Kilner | forcep
3. | Boyd | scissor Small
4. | Boyd | scissor large
5. | Boyd | forcep
6. | Boyd | clamp
Could you help me mysql query to handle below operation
If we search 'boyd' then numbers 3 4 5 and 6 should come up.
If we search 'scissor' then numbers 1 3 and 4 should come up.
If we search 'boyd scissor', numbers 3 and 4 should come up.
If they search' Kilner scissor' then only no 1 should display.
Let me know
thanks
the way to do it in mysql is full text search
SELECT *, MATCH(field) AGAINST ('word1 word2 word3') AS score
FROM table
WHERE MATCH(field) AGAINST('word1 word2 word3')
look this tutorial http://devzone.zend.com/26/using-mysql-full-text-searching/
try this query
SELECT * FROM `table` WHERE `name` LIKE '%$search_var%'
PDO structure
$db = $this->pdo->prepare("SELECT * FROM `table` WHERE `name` LIKE :mysearch");
$db->execute( array("mysearch"=>'%'.$mysearch.'%') );
The query you ask is a bit complex. You want to return matches in both columns, but if both columns match, then single matches have to be discarded.
This means, one way or another, run a query requiring two matches and one requiring one match, comparing the results and returning the appropriate set.
Performance-wise, I believe it is better to run one query that will fetch both, and then handle the results in PHP (you could handle them in MySQL through the use of a superquery).
So:
// We split keywords
$keywords = array_unique(preg_split('/\s+/', $search));
$inset = array();
foreach($keywords as $keyword)
$inset[] = "'".mysql_real_escape_string($keyword)."'";
$sql_in = '('.implode(',', $inset).')';
$query = "SELECT *, IF(type IN $sql_in, 1,0)+IF(pattern IN $sql_in,1,0) AS matches FROM mytable WHERE (type IN $sql_in) OR (pattern IN $sql_in) ORDER BY matches DESC;";
The above uses the discouraged mysql_ functions. Using PDO, that would be:
$keywords = array_unique(preg_split('/\s+/', $search));
// Generate a (?,?,?..?) template as long as $keywords
$sql_in = '('.implode(',', array_fill(0, count($keywords), '?')).')';
$query = "SELECT *, IF(type IN $sql_in, 1,0)+IF(pattern IN $sql_in,1,0) AS matches FROM mytable WHERE (type IN $sql_in) OR (pattern IN $sql_in) ORDER BY matches DESC;";
$st = $db->prepare($query);
$st->execute($keywords);
Note that the above uses exact match, so "Boyd" will retrieve a match with "Boyd", but "Boy" won't. Use the % matching character to change this behaviour.
Now we retrieve a table which is identical to MyTable but has one extra column, "matches", containing either 2 or 1. Can't contain 0 because of the WHERE limitation: one of the two matches must be true and count as 1.
The 2's will be returned first, so we can do
if (!isset($matches))
$matches = $tuple['matches'];
else
if ($tuple['matches'] < $matches)
break;
that is, we save the first (and highest) value, and only accept that value for the subsequent tuples. As soon as an inferior match comes by, we exit the loop and close the cursor.
This may be done in MySQL with
SELECT * FROM ( the above query ) AS newTable
WHERE matches = (
SELECT MAX(matches) FROM ( the above query ) AS tmpTable
);
but it incurs a performance penalty.
$search=array('byod','scissor');
$st=""; $st2="";
foreach($search as $value){$st.="type=%$value% or ";$st2.="pattern=%$value% or ";}
$st2=substr($st2,0,-3);
echo "select * from tablename where $st $st2";

mysql get many id's on one row

How to get all ids separated by comma on one row.
id | name
1 | Jonny
2 | Lisa
3 | Ben
And with php/mysql get with one query without a loop the ids comma separated. Like "1,2,3"
To be something like this :
$query = "SELECT 1,2,3 as oneRowIds FROM tableName";
$result = mysql_query($query);
$result = mysql_fetch_assoc($result);
echo $result['oneRowIds'];// and that shows "1,2,3"
use group_concat function
GROUP_CONCAT() function is used to concatenate column values into a single string. It is very useful if you would otherwise perform a lookup of many row and then concatenate them on the client end.
select group_concat(id) as oneRowIds FROM tableName

How to check MySQL results during a 'while' table generation

Lets see if I can explain this. I am displaying a table in PHP with up/downvote arrows. PHP calls a MySQL query to get the data, then places it in a table with a "while" loop. During this loop, I want to check and see if a user has already upvoted a row, and represent that with a different looking up arrow, etc. This is how I have gone about this so far.
If a user upvotes something, it is stored in a mysql db that looks something like this:
username| upvote| item_id
Bob | 1 | 2293
Bob | 1 | 2295
Sally | 1 | 2295
How do I tell php to check if "Bob" has a "1" on item "2293" in the middle of a while loop of a different MySQL array?
echo '<table>';
while ($row = mysqli_fetch_array($data)) {
echo '<tr>';
//insert php statement checking $row2 to see if Bob has upvoted the data in this row
//so I can place the appropriate arrow here
echo '</tr></table>';
}
What you need here is probably a MySQL join query. An example could be:
Your existing SQL:
SELECT * FROM `items`
We then join all rows from table "upvotes", but only those rows which the current user has placed:
The final SQL:
SELECT `items`.*, COUNT(`upvotes`.`item_id`) AS `upvotes` FROM `items` LEFT JOIN (`upvotes`) ON (`upvotes`.`username` = $currentUserName AND `items`.`id` = `upvotes`.`item_id`) GROUP BY `items`.`id`
Then you should be able to use the same PHP code, but now you can check if "$row['upvotes'] > 0".

Categories