mysql - finding string from array - mysql

Database table:
id| p1 | p2 | notes
1 | 1 | a | cat, mouse, dog
2 | 1 | a | cat, horse, dog
I now need to run a query that selects the row where "notes" does not contain a string defined in the $exclusions array. I have tried the LIKE '%mouse%' operator, but that gave an error.
$exclusions = array ("mouse");
if($row['p1'] == 1 && $row['p2'] == "a" && $row['notes'] not like '%mouse%') {...}
Thank you.

Looks like you are doing the logic in a mix of PHP code and sql. To do it in php, you can do
!strstr($row['notes'], 'mouse')
That says "If there is no occurrence of "mouse" in $row['notes']"
The ! will make it return true if there is no occurrence.

if($row['p1'] == 1 && $row['p2'] == "a" && $row['notes'] not like '%mouse%') {...}
This is not MySQL syntax. It looks like PHP, and in PHP you can not use LIKE. Try a string comparison operator like strstr. http://php.net/manual/en/function.strstr.php
Mysql Style
A query to get all rows without mouse could be this:
SELECT * FROM `tablename`
WHERE `notes` NOT LIKE '%mouse%';
Or to get the exclusions from a php array:
$condition = "WHERE ";
$first = true;
foreach($exclusions as $ex) {
if(!$first) $condition .= " AND "; // or use OR
$condition .= "`notes` NOT LIKE \"%$ex%\"";
$first = false;
}
$complete_query = "SELECT * FROM `tablename` $condition;";

Related

MySQL optional filters for search query

I am working on a query that has an optional filter, so lets assume the table name is products and the filter is the id (primary key)
If the filter is not present I would do something like this:
SELECT * FROM products;
If the filter is present I would need to do something like this:
SELECT * FROM products WHERE id = ?;
I have found some potential solutions that can mix the 2 in sql rather than doing conditions in the back-end code itself
SELECT * FROM products WHERE id = IF(? = '', id, ?);
OR
SELECT * FROM products WHERE IF(? = '',1, id = ?);
I was just wondering which one would be faster (In the case of multiple filters or a very big table) Or is there a better solution to handle this kind of situation?
A better approach is to construct the WHERE clause from the parameters available. This allows the Optimizer to do a much better job.
$wheres = array();
// Add on each filter that the user specified:
if (! empty($col)) { $s = $db->db_res->real_escape_string($col);
$wheres[] = "collection = '$s'"; }
if (! empty($theme)) { $s = $db->db_res->real_escape_string($theme);
$wheres[] = "theme = '$s'"; }
if (! empty($city)) { $s = $db->db_res->real_escape_string($city);
$wheres[] = "city = '$s'"; }
if (! empty($tripday)) { $s = $db->db_res->real_escape_string($tripday);
$wheres[] = "tripday = '$s'"; }
// Prefix with WHERE (unless nothing specified):
$where = empty($wheres) ? '' :
'WHERE ' . implode(' AND ', $wheres);
// Use the WHERE clause in the query:
$sql = "SELECT ...
$where
...";
Simplest approach is OR:
SELECT *
FROM products
WHERE (? IS NULL OR id = ?);
Please note that as you will add more and more conditions with AND, generated plan will be at least poor. There is no fit-them-all solution. If possible you should build your query using conditional logic.
More info: The “Kitchen Sink” Procedure (SQL Server - but idea is the same)

Why does my find_in_set match for a single value only and not for comma separated values?

I have a problem in matching with find_in_set; it does not matches for multiple comma separated values.
Below is what i have tried
$skills = array('php','html','laravel','nodejs');
$skills = implode(',', $skills);
$sql = "SELECT * FROM jobs_posted_by_employer WHERE FIND_IN_SET(skills, :array)";
$stmt = $db->prepare($sql);
$stmt->bindParam('array', $skills);
For this table, the above query...
+-----------------------+
| skills |
+-----------------------+
| php | => matches
+-----------------------+
| php,laravel,html | => does not match--why?
+-----------------------+
| html | => matches
+-----------------------+
|php,html,laravel,nodejs| => does not match -- why?
+-----------------------+
Thanks in Advance!!!
#Goutham, you can do what you want by using a loop in PHP to build a set of OR statements that takes each element of your string array and creates successive individual find_in_set statements with an OR between them. What you want to end up with is a query that checks for each element in your array, against the set. And don't implode your array into a string, because you need to use it as an array.
$skills = array('php','html','laravel','nodejs');
$sql = "SELECT * FROM jobs_posted_by_employer WHERE ";
for($x=0;$x<count($skills);$x++){
if($x>0){$sql .=" OR ";}
$sql .=" WHERE FIND_IN_SET(".$skills[$x].", :array)";
}
$sql .=";";
$stmt = $db->prepare($sql);
$stmt->bindParam('array', $skills);
You misunderstand how FIND_IN_SET works.
FIND_IN_SET('html', 'php,html,laravel,nodejs') is true, because the string 'html' is in the set 'php,html,laravel,nodejs'.
FIND_IN_SET('php,laravel,html', 'php,html,laravel,nodejs') is false, because the string 'php,laravel,html' is not in the set 'php,html,laravel,nodejs'.
Don't store values separated in a database table column. Have a separate table to link the single skills to each jobs_posted_by_employer record in order to query the data easily.

MySQL Query: Concatenate horizontally based on selected ids

Say I have a table 'table_name' with two columns like this:
table_name
------------
my_id | data
------|-----
id1 | 312
id1 | 523
id1 | 128
id2 | 239
id2 | 479
id2 | 121
id3 | 639
id3 | 429
id3 | 131
id4 | 473
id4 | 872
id4 | 662
id4 | 174
id4 | 272
I tried around a while and I now found a way to select the ids I want to use:
SELECT DISTINCT my_id from table_name WHERE (my_id REGEXP 'id[234]')
This gives me the ids 'id2', 'id3' and 'id4'. How would I formulate a query that gives me my desired output, based on the selected ids as below?
id2 | id3 | id4
---------------
239 | 639 | 473
479 | 429 | 872
121 | 131 | 662
NaN | NaN | 174
NaN | NaN | 272
If your table really only has those two columns and there is no related data that can be used to order the data column like you have shown, then there is no good way to achieve the ordering you're looking for.
Relational data doesn't have any intrinsic "order" to it, even if you've inserted that data in a particular order or displayed it in a certain way here. If your table really only has those two columns, it will be difficult to match the "first" id2 value with the "first" id3 value and so on to get to your desired output. We could potentially rank them in a query and match them based upon that rank (ascending or descending) or even provide some random order capability, but there is no documented (i.e. reliable) way to get the order that you've provided.
While a table does have a physical order to the underlying bits in storage, and some products allow you to access them via a physical rowid (Oracle), no RDBMS that I know of (including MySql) guarantees the order in which the rows will be returned unless an order by clause is used in your select statement. This is literally by design and is considered a "feature" that came out of E.F. Codd's research.
First make a function that select distinct of the id's
public function get_id_of_table_name() {
$sql = 'SELECT DISTINCT my_id ';
$sql .= 'FROM table_name ';
$query = $this->db->query($sql);
$result = $query->row();
foreach ($result as $key => $value)
{
$result->data = $this->get_data($result->my_id);
}
return ( $query->num_rows() ) ? $result : FALSE;
}
And create the second function that will gather all the data's base on what id's
public function get_data($my_id) {
$params = [];
$sql = 'SELECT data ';
$sql .= 'FROM table_name ';
$sql .= 'WHERE my_id = ? ';
$params[] = $my_id;
$query = $this->db->query($sql, $params);
$result_data = $query->result();
$data = [];
foreach ($result_data as $result)
{
array_push($data, $result->data);
}
return $data;
}
You can put a where clause in the first function if you want.
$sql .= 'WHERE my_id = ? ';
and add the params
$params[] = $my_id;
You can also add parameters my_id as array in the first function so that you can get what id you want to get
$id = ["id2","id3","id4"];
public function get_id_of_table_name($id) {
$params = [];
$sql = 'SELECT DISTINCT my_id ';
$sql .= 'FROM table_name ';
$sql .= 'WHERE 1 ';
foreach ($id as $my_id)
{
$sql .= 'OR (my_id = ?) ';
$params[] = $my_id;
}
$query = $this->db->query($sql, $params);
$result = $query->row();
foreach ($result as $key => $value)
{
$result->data = $this->get_data($result->my_id);
}
return ( $query->num_rows() ) ? $result : FALSE;
}

using a string of values in WHERE clause - mysql

I have a string of values like :
$cat = "1,5,6,8,9";
now I would like to use that variable in WHERE clause. how do I do it ?
"select category from test where category...?"
I am using below code but I get null from number_of_result variable :
$array_of_cat = explode(",",$cat);
if($number_of_result == 0){
$mresult = mysql_query("select * from books where
GoodName like '%$title%' and GroupCode in ($array_of_cat) ");
$number_of_result = mysql_num_rows($mresult);
}
Change your SQL statement to this one. Use implode() to pass array elements in IN clause
$mresult = mysql_query("
SELECT * FROM books
WHERE GoodName LIKE '%$title%' AND GroupCode IN (" . implode(",", $array_of_cat) . ")");
You do not need to explode the variable - doing so results in an array that will result in the wrong value (the string "Array") when interpolated into the SQL string.
Despite the fact that this is unsafe (SQL injection prone) you could do:
if($number_of_result == 0){
$mresult = mysql_query("select * from books where
GoodName like '%$title%' and GroupCode in ($cat)");
$number_of_result = mysql_num_rows($mresult);
}
I strongly suggest you use the mysql_real_escape_string function to prepare your variables.
$cat = array(1,5,6,8,9);
$array_of_cat = implode(",",$cat);
if($number_of_result > 0){
$mresult = mysql_query("select * from books where
GoodName like '%$title%' and GroupCode in ($array_of_cat) ");
$number_of_result = mysql_num_rows($mresult);
}
Also, I'd strongly suggest reading up on PDO/MySQLi

Select next column to right mysql?

If I have a variable in php like,
$var = 'aaa';
And my mysql database has 2 columns
| aaa | bbb |
Is there a way I can select bbb using $var, basically select the column next to $var on the right?
Use mysql_query("SHOW COLUMNS FROM {table}",$db) to get a list of columns and use that to figure out the name of the column next to aaa. You can then use that in further queries.
Implementing this results in something in the lines of (untested):
$columns = mysql_query("SHOW COLUMNS FROM {table}",$db) or die("mysql error");
if (mysql_num_rows($columns) > 0) {
while ($row = mysql_fetch_assoc($columns)) {
if ($prev == 'aaa') {
$nextcol = $row['Field']; // 'bbb' in this case
break;
}
$prev = $row['Field'];
}
}