Not searching what I want with LIKE in Codeigniter, MySQL - php

I have the followings examples in be_user_profiles.subject. These are subject ids which each teacher teaches.
1// English
1,2 // English and Math etc
1,2,14
2,4,114
12,24,34
15, 23
I want to select where be_user_profiles.subject has 1. When I use the following, it outputs all which has 1 in it. So it will outputs all. I tried HAVING but it picks up only exact matches. So it shows only the first one. How can I pick up data which has the be_user_profiles.subject?
$this->db->select('*');
$this->db->from('be_user_profiles');
$this->db->join('be_users', 'be_users.id = be_user_profiles.user_id');
$this->db->where('be_users.group', $teachergrp);
$this->db->like('be_user_profiles.subject', $subjectid);
//$this->db->having("be_user_profiles.subject = $subjectid");// this picks up only exact match
$query = $this->db->get();
Thank you in advance.

be_user_profiles table
row1: 1,2,14
row2: 2,4,114
row3: 12,24,34
row4: 15, 23
To get data with exact match use this query
$this->db->query("
SELECT * FROM `be_user_profiles`
WHERE subject LIKE '1'
UNION
SELECT * FROM `be_user_profiles`
WHERE subject LIKE '1,%'
UNION
SELECT * FROM `be_user_profiles`
WHERE subject LIKE '%,1,%'
UNION
SELECT * FROM `be_user_profiles`
WHERE subject LIKE '%,1'
");

The both clause that you put into the like query means to add % widcard in front and after of the string to search, so it returns 1 as long as 12, 21, 121 etc. If you remove it it will search only for exact match.
You could add this like clause and add commas to it and i think that it will work. Try to add this instead of the like you have now:
$this->db->like("," . "be_users.group" . "," , "," . $subjectid. "," , both);

I think you can use a regex pattern here.
$pattern = "(^|.*,)1(,.*|$)";
...
...
$this->db->select('*');
....etc
$this->db->where("be_user_profiles.subject REGEXP $pattern");
This regex pattern assumes that there are no spaces in the comma string.
However, as #halfer said in the comments you really, really should split this out into a "teachersubject" table with teacherid and subjectid columns otherwise it will bite you in the backside very, very soon. [Been there, done that :-) ]
eg Imagine trying to expand the above into searching for a teacher that teaches ((maths or physics) and English). Nightmare!

Related

How to go over comma separted values in MYSQL

My database structure is like this:
Movie Name GenreID**
Movie1 1,2,3
Movie2 2,4
Movie3 4,5,16
I need to select a Movie name based on the Genre ID the user selected which I put inside the genreIDArray[]
Let's say for example the genreIDArray has values: $genreIDArray = ['1','2','3'];
My current query method is the ff:
Here I prepared each ID into parts so the result won't become genreID LIKE (%1,2,3%) because I checked this doesn't work.
So I did this separation loop:
$queryParts = array();
foreach($genresIDArray as $genreID) {
$queryParts[] = "'%".$genreID."%'";
}
After the separation loop I put together the final query:
$genreString = implode(" OR genreID LIKE ",$queryParts);
$genreQuery = " SELECT * FROM movies WHERE (genreID LIKE {$genreString}) ";
gave me this final query output:
SELECT * FROM movies WHERE (genreID LIKE '%1%' OR genreID LIKE '%2%' OR genreID LIKE '%3%')
This actually works, but apparently not that efficient because genreID 11,12,13 and so on that start with 1 is also selected. I think I'm missing the MYSQL LIKE logic here. I've tried '%$genreID' which means to select the starting or first number/letter of a table data, but that's still the same thing, $genreID% doesn't and would not work because this only means genreid ENDING letters/number will be selected.
I hope I spelled that out clear enough. I'm in a bind here. Please help.
Thank you so much.
There is a very cool function for that. You can use FIND_IN_SET.
SELECT * FROM test WHERE FIND_IN_SET(1,colors)
But if its possible you should avoid such structures in your database and normalize your database.

MySQL Select data separated strings

I am trying to select a record using the LIKE function. However, it does not show results if there are characters in between. I want it to select data that contains those strings. For example:
$value = "Mark Anthony";
$qry ="SELECT * FROM students WHERE name LIKE '%$value%'";
returns these results:
John Mark Anthony
Mark Anthony Philipps
but I also want to have results like these
Mark James Anthony
Mark Gabriel Anthony Fernandez
Marko Julian Anthonyo
Any ideas?
UPDATE: 'Mark' must be before 'Anthony'
I think Full TEXT works
But Full-text searches are supported for MyISAM tables only
SELECT * FROM students
WHERE MATCH (name)
AGAINST ('Mark Anthony' IN BOOLEAN MODE)
UPDATE:- As per question update OP need to search Marko as well, then you can get like this:-
SELECT * FROM students
WHERE
(
name LIKE '%Mark%'
OR name LIKE '%Anthony%'
)
You could split the value string into two parts. Like so:
WHERE name LIKE '%Mark%' AND name LIKE '%Anthony%'
last try:
$value = "Mark Anthony";
$value = str_replace(" ","%",$value);
$qry ="SELECT * FROM students WHERE name LIKE '%$value%'";
not tested!
Try this solution -
SELECT * FROM table WHERE column REGEXP '(Mark).+(Anthony)';
The proplem is, you say "bring all results which contains Mark Anthony" so it does. You should set it like
$value = "Mark%Anthony";

Fetch string of all id from database using query

Hello i Have tableuser, with column id and many more. now i want all id in string form concatenated with comma separation and appending prefix as A.
means suppose i have records with id 1, 2, 3, 4 etc
now i want result like A1,A2,A3 like this
i did it with my way but its too complex i want to do it with single query.
my code are as under its working fine.
$send_idstring='';
$qry="SELECT concat('A',id) as id FROM `admin` WHERE concat(fname,' ',lname) LIKE '%".addContent($searchVal)."%' ";
$send_id=mysql_query($qry);
while($row=mysql_fetch_assoc($send_id)){
$send_idstring.=$row['id'].',';
}
$send_idstring=trim($send_idstring, ",");
echo $send_idstring;
it gives me output as i want but i want another way to do it please suggest.
Try
SELECT GROUP_CONCAT(CONCAT('A', `id`) SEPARATOR ',') AS idList FROM `admin`;
http://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat

Mysql LIKE clause and separate words in a field

I currently use a mysql statement like the one below to search post titles.
select * from table where title like %search_term%
But problem is, if the title were like: Acme launches 5 pound burger and a user searched for Acme, it'll return a result. But if a user searched for Acme burger or Acme 5 pound, it'll return nothing.
Is there a way to get it to return results when a users searches for more than one word? Is LIKE the correct thing to use here or is there something else that can be used?
You could use a REGEXP to match any of the words in your search string:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]](', REPLACE('Acme burger', ' ', '|'), ')[[:>:]]')
Please notice that this will not be very efficient. See fiddle here.
If you need to match every word in your string, you could use a query like this:
select *
from tbl
where
title REGEXP CONCAT('[[:<:]]', REPLACE('Acme burger', ' ', '[[:>:]].*[[:<:]]'), '[[:>:]]')
Fiddle here. But words have to be in the correct order (es. 'Acme burger' will match, 'burger Acme' won't). There's a REGEXP to match every word in any order, but it is not supported by MySql, unless you install an UDF that supports Perl regexp.
To search for a string against a text collection use MATCH() and AGAINST()
SELECT * FROM table WHERE MATCH(title) AGAINST('+Acme burger*')
or why not RLIKE
SELECT * FROM table WHERE TITLE RLIKE 'Acme|burger'
or LIKE searching an array, to have a compilation of $keys
$keys=array('Acme','burger','pound');
$mysql = array('0');
foreach($keys as $key){
$mysql[] = 'title LIKE %'.$key.'%'
}
SELECT * FROM table WHERE '.implode(" OR ", $mysql)
What you need to do is construct a SQL such that, for example:
select * from table where title like "%Acme%" and title like "%burger%"
In short: split the string and create one like for each part.
It might also work with replacing spaces with %, but I'm not sure about that.
The best thing is thing use perform union operation by splitting your search string based on whitespaces,
FOR Acme 5 pound,
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME 5 POUND%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%ACME%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%5%'
UNION
SELECT * FROM TABLE WHERE TITLE LIKE '%POUND%'
Find out a way to give the first query a priority. Or pass the above one as four separate queries with some priority. I think you are using front end tp pass query to data bases, so it should be easy for you.
<?php
$search_term = 'test1 test2 test3';
$keywords = explode(" ", preg_replace("/\s+/", " ", $search_term));
foreach($keywords as $keyword){
$wherelike[] = "title LIKE '%$keyword%' ";
}
$where = implode(" and ", $wherelike);
$query = "select * from table where $where";
echo $query;
//select * from table where title LIKE '%test1%' and title LIKE '%test2%' and title LIKE '%test3%'

Advanced MySQL Search Help

I've been trying to come up with something for a while now to no avail. My MySQL knowledge is rudimentary at best so I could use some guidance on what I should use for the following:
I have 2 tables ('bible' and 'books') that I need to search from. Right now I am just searching 'bible' with the following query:
SELECT *
FROM bible
WHERE text LIKE '%" . $query . "%'
ORDER BY likes DESC
LIMIT $start, 10
Now, I need to add another part that searches for some pretty advanced stuff. Here is what I want to do in pseudocode which I am aware doesn't work:
SELECT *
FROM bible
WHERE books.book+' '+bible.chapter+':'+bible.verse = '$query'
$query would equal something like Genesis 1:2, Genesis coming from books.book, 1 coming from bible.chapter and 2 coming from bible.verse
Any help/guidance on this is much appreciated =)
I would recommend designing a way in your application code to break up that query so that you search for the book, chapter, and verse separately from the keyword.
That means you need columns for book, chapter, and verse that are separate from the verse text.
You should also use a FULLTEXT index because the LIKE wildcard searches are extremely inefficient.
Here's how I'd run the query in PHP using PDO:
$quoted_query = $pdo->quote($query);
$sql = "SELECT * FROM bible
WHERE book = ? AND chapter = ? AND verse = ?
AND MATCH(text) AGAINST ({$quoted_query})"
$stmt = $pdo->prepare($sql);
$stmt->execute(array($book, $chapter, $verse));
I'd rather use a parameter for the fulltext query too, but MySQL doesn't support that.
You're close. To concatenate the fields use the CONCAT() function:
SELECT * FROM bible WHERE CONCAT(books.book, ' ', bible.chapter, ':', bible.verse) = '$query'
You can use MySQL concatenation:
SELECT *
FROM bible JOIN books
WHERE CONCAT(books.book, ' ', bible.chapter, ':', bible.verse) = '$query'
I'm not sure what your foreign key is linking books to bible, but that may need specification as well.
You need to parse the query into book, chapter and verse in php first.
A regular expression should work:
preg_match("/(.+)([0-9]+):([0-9]+)/",$query,$matches);
$book = trim(matches[1]); // use trim to remove extra spaces
$chapter = matches[2];
$verse = matches[3];
Then your sql query becomes:
SELECT *
FROM bible
WHERE books.book = '$book' AND bible.chapter= '$chapter' AND bible.verse ='$verse'
-- watch out for sql injection here! use prepared statements!

Categories