i am Performing the MySQL query with Where In conditions.
Here is my Query.
The query should be:
SELECT * FROM users WHERE id IN (44,44,33,44,33,0);
Query showing my correct result, no problem at all,
but what i want to do is Can we Divide all the id with the individual conditions ?
Or can a query has multiple Where In for a single column?
like
SELECT * FROM users WHERE id IN (44)
AND id IN (45)
AND id IN (46);
like this.
Is that possible ? ?
My query code for performing the query, its in Laravel.
$films = Film::with('genre')->with('languages')->with('likes')->with('comments')->with('likedBy');
if(Input::get('sort')){
$sort = Input::get('sort');
switch ($sort){
case 'old_new':
$films = $films->orderBy('created_at', 'asc');
break;
case 'new_old':
$films = $films->orderBy('created_at', 'desc');
break;
case 'views':
// $films = DB::table('films')
// ->leftJoin('film_views', 'films.id', '=', 'film_views.film_id')
// ->select(DB::raw('films.*, count(film_views.film_id) as views'))
// ->groupBy('films.id')
// ->orderBy('views' , 'desc')
// ;
$films = $films
->leftJoin('film_views', 'films.id', '=', 'film_views.film_id')
->select(DB::raw('films.*, count(film_views.film_id) as views'))
//->whereBetween('created_at', [$this->first_day_of_search, $this->final_day_of_search])
->groupBy('films.id')
->orderBy('views' , 'desc')
;
break;
case 'likes':
$films = $films
->leftJoin('film_likes', 'films.id', '=', 'film_likes.film_id')
->select(DB::raw('films.*, count(film_likes.film_id) as likes'))
->groupBy('films.id')
->orderBy('likes' , 'desc')
;
break;
}
}
if(Input::get('filter')) {
$jsonFilter = Input::get('filter');
$filters = json_decode($jsonFilter);
foreach ($filters as $filter => $value){
switch ($filter){
case "genre":
if($value){
$films = $films->whereHas('genre', function ($query) use($value) {
$query->whereIn('genre_id', $value);
});
}
break;
case "cert":
if($value){
$films = $films->whereIn('cert', $value);
}
break;
case "country":
if($value){
$films = $films->whereIn('country', $value);
}
break;
case "lang":
if($value){
$films = $films->whereHas('languages', function ($query) use($value) {
$query->whereIn('language_id', $value);
});
}
break;
}
}
}
$films = $films->paginate(5);
return parent::api_response($films->toArray(), true, ['return' => 'all films'], 200);
I will post an answer if for no other reason than amusement. I believe that a WHERE IN clause is internally converted into a series of equality onditions separated by OR. So your original query
SELECT * FROM users WHERE id IN (44,44,33,44,33,0)
would be internally converted to this
SELECT * FROM users WHERE id = 44 OR id = 44 OR id = 33 OR id = 44 OR
id = 33 OR id = 0
So having a single number for your IN clause would be equivalent to a single equality condition.
By the way, you have the same numbers appearing multiple times, which doesn't make any sense.
Yes, it is possible to have multiple WHERE IN.
SELECT * FROM users WHERE id IN (44) OR id IN (45) OR id IN (46);
This is correct.
However I don't understand why you want to do this because this is low in performance compared to having one IN
Related
I have a changeable output from the database like this:
1,2,3,4 and sometimes 5,4,9
I want to add a not like where clause depending on the user:
For example:
User 1
$products = \App\Product::where('user', '1')
->where(['category', 'not like', '1,2,3,4')
->get();
User 2
$products = \App\Product::where('user', '2')
->where(['category', 'not like', '5,4,9')
->get();
https://laravel.com/docs/5.8/queries#where-clauses
$products = \App\Product::where('user','2')
->whereNotIn('category', [5, 4, 9])
->get();
If all you need is to change the category them why not make it a variable like this.
$categories = $userId == 1 ? [1,2,3,4] : [5,4,9];
$products = \App\Product::where('user',$userId)
->whereNotIn('category', $categories)
->get();
So my guess is that you need to have some method to see which categories a user should have that would be more complex than this, but well I hope you get the idea.
Another way
$user_id = $request->input('id');//Put your user id in variable either by request or anyway you want to save
$category_arr = [];
if($user_id == 1) {
$category_arr = [1,2,3,4];
} elseif ($user_id == 2) {
$category_arr = [5,4,9];
} else {
echo "Error Msg"
}
$products = \App\Product::where('user',user_id)
->whereNotIn('category', $category_arr)
->get();
This is an answer that extend the Roman Bobrik's an Eli's.
The goal is to let your request to be able to handle a default condition while handling specific request when you need to.
if ($request->input('id') == 1) {$categories = [1,2,3,4];}
if ($request->input('id') == 2) {$categories = [5,4,9];}
$products = \App\Product::where('user', $request->input('id'))
->when(isset($categories), function($query) use($categories) { // This will be applied for specified users. In this case, users id = 1 || 2
return $query->whereNotIn('category', $categories);
})->when(!isset($categories), function($query) { // This will be applied when users id != 1 || 2
return $query->whereNotIn('category', [1,2]); //Define your default categories for every users that are not specified at the begining.
})->get();
You could also save the categories array to the users table and change the when() condition for when(Auth::user()->categories != null) and when(Auth::user()->categories == null).
The only warning is, when you use that kind of query, you must have two when() condition that are the exact opposite. Because if none of the both condition are respected, the final query will be $products = \App\Product::where('user', $request->input('id'))->get(); and I'm sure that you won't that to happen.
Well, you can chain more than two when() condition, but be sure to have one that will catch everything that was not catch by any other.
If your changeable output is an array, you can try this:
$categories = [1, 2, 3, 4];
$products = \App\Product::where('user', 1)
->whereNotIn('category', $categories)
->get();
Codeigniter Active records query gives me error. how to put SOUNDS LIKE into where clause.
function _search($type, $q, $qes, $sort = null, $start = 0) {
$type = strtolower($type);
$q = strtolower($q);
$this->db->select("*");
$this->db->from("books");
$this->db->where("SOUNDEX(name) IN({$q})");
foreach($qes as $k){
$this->db->or_where("name SOUNDS LIKE '$k'");
}
foreach($qes as $k){
$this->db->or_where("name LIKE '%$k%'");
}
$this->db->where("status", 1);
if ($type != NULL) {
$this->db->where("LOWER(type)", $type);
}
//$this->db->like("LOWER(name)", $q);
$this->db->limit(BWK_MAX_BOOK_SIZE, $start);
switch ($sort) {
case 1:
break;
case 2:
$this->db->order_by("sellingPrice", "ASC");
break;
case 3:
$this->db->order_by("sellingPrice", "DESC");
break;
case 4:
$this->db->order_by("created", "DESC");
break;
}
this gives me query when i echo query. i am searching for technologi i need to get technology technologies etc.
SELECT * FROM `books` WHERE SOUNDEX(name) IN('t254') OR `name` `SOUNDS` LIKE 'technolog' OR `name` LIKE '%technologi%' AND `status` = 1 AND LOWER(type) = 'school' LIMIT 50
getting error
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '`SOUNDS` LIKE 'technolog' OR `name` LIKE '%technolog%' AND `status` = 1 AND LOWE' at line 4
every thing works fine but when i put SOUNDS LIKE it gives me error.
its probably the best to group things here
you can try the following
$this->db
->select('*')
->from('books')
->where_in('SOUNDEX(name)', $q, NULL);
if (is_array($qes) && count($qes) > 0)
{
$this->db->group_start();
foreach($qes AS $k)
{
$this->db->or_group_start();
$this->db
->where('name SOUNDS LIKE '.$this->db->escape($k), NULL, false)
->or_like('name', $k);
$this->db->group_end();
}
$this->db->group_end();
}
if (!is_null($type))
{
$this->db->where('LOWER(type)', $type);
}
switch ($sort) {
case 1:
break;
case 2:
$this->db->order_by("sellingPrice", "ASC");
break;
case 3:
$this->db->order_by("sellingPrice", "DESC");
break;
case 4:
$this->db->order_by("created", "DESC");
break;
}
echo $this->db
->where('status',1)
->limit(BWK_MAX_BOOK_SIZE, $start)
->get_compiled_select();
this would produce a statement like
SELECT *
FROM `books`
WHERE SOUNDEX(name) IN('t254') AND
(
(
name SOUNDS LIKE 'technologi' OR
`name` LIKE '%technologi%' ESCAPE '!'
)
OR
(
name SOUNDS LIKE 'whatever' OR
`name` LIKE '%whatever%' ESCAPE '!'
)
)
AND `status` = 1
AND LOWER(type) = 'school'
LIMIT 50
From : DB_query_builder.php, what one can see is 3rd argument decides whether to escape or not.
public function or_where($key, $value = NULL, $escape = NULL){
}
So just tell that not to escape it
$this->db->or_where("name SOUNDS LIKE '$k'", NULL, FALSE);
Could you use the HAVING clause with your ORDER BY and your LIKE?
HAVING clause:
https://www.w3schools.com/sql/sql_having.asp
Earlier this day a asked a question about an update query. But now i want to select some things ( and it is working ) but I also want to order them and put a limit on it.
This is the code to select all the food :
public function getFood($id)
{
$id = (int)$id;
$rowset = $this->tableGateway->select(array('kindOfFood_id' => $id));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $id");
}
return $row;
}
But how can i do this :
Select * from KindOfFood ==> order by kindOfFood_votes DESC ?
I saw on the documentation you can do something like this, but it doesn't work with me?
$rowset = $artistTable->select(function (Select $select) {
$select->where->like('name', 'Brit%');
$select->order('name ASC')->limit(2);
});
Are you looking to return only single row or multiple rows.
Try this for multiple rows -
use Zend\Db\Sql\Select; //at the top of the page among other use statements.
public function getFood($id)
{
$id = (int) $id;
$select = new Select(TABLE_NAME); //CHANGE TABLE_NAME as per needs
$select->where('kindOfFood_id = ' . $id);
$select->order('kindOfFood_votes DESC');
$resultSet = $this->tableGateway->selectWith($select); //Will get array of rows.
//$row = $rowset->current(); THIS IS FOR RETURNING ONLY SINGLE ROW NOT ALL ROWS
if (!$resultSet) {
throw new \Exception("Could not find rows with food id - $id");
}
return $resultSet;
}
Can access the returned resultSet via loop. Eg: foreach
foreach($resultSet as $row) {
echo $row->kindOfFood_id; //or something
}
Note:
If you need only
Select * from KindOfFood order by kindOfFood_votes DESC
then remove the $select->where('kindOfFood_id = ' . $id); line from above.
I want to run following query in symfony doctrine.
SELECT p.id AS id FROM skiChaletPrice p WHERE ski_chalet_id = ? AND month = ?
I wrote my doctrine query as following.
$q = Doctrine_Query::create()
->select('p.id AS id')
->from('skiChaletPrice p')
->andWhere('ski_chalet_id = ?', $chaletId)
->andWhere('month = ?', $from);
$result = $q->fetchOne();
if ($result->count() > 0) {
return $result->toArray();
} else {
return null;
}
But my result always include all columns in the table. What the issue? Please help me.
The issue is that fetchOne() will return a Doctrine object, which implicitly contains all the columns in the table. $result->toArray() is converting that doctrine object to an array, which is why you get all the columns.
If you only want a subset of column, don't hydrate an object, instead do something like this:
$q = Doctrine_Query::create()
->select('p.id AS id')
->from('skiChaletPrice p')
->andWhere('ski_chalet_id = ?', $chaletId)
->andWhere('month = ?', $from);
$results = $q->execute(array(), Doctrine::HYDRATE_SCALAR);
See http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/data-hydrators.html
This is how I should do it:
$result = Doctrine_Query::create()
->select('id')
->from('skiChaletPrice')
->andWhere('ski_chalet_id = ?', $chaletId)
->andWhere('month = ?', $from)
->limit(1)
->fetchOne(array(), Doctrine_Core::HYDRATE_SINGLE_SCALAR);
// result will be a single id or 0
return $result ?: 0;
// if you want array($id) or array() inseatd
// return (array) $result;
I have search for a long time to get this thing work.
What I want is to know how I user the 'distinct' in a zend db model to make my selection for the followers of a user unique.
My db model to count followers for a user (here I need to add the 'distinct')
public function countFollowers($user_id)
{
$rowset = $this->fetchAll("user_id = $user_id");
$rowCount = count($rowset);
if ($rowCount > 0) {
return $rowCount;
} else {
return $rowCount;
}
}
EDIT: This function is part of 'class Application_Model_DbTable_Followers extends Zend_Db_Table_Abstract'
My table structure
id
article_id // Id of the article who is written by 'user_id'.
user_id // user_id owner of the article
follower_id // member who has following this article
date // date of follow
'user_id' can be written various articles, the follower can follow various articles of the same writer. I want to make a unique follower count. As an example what I want, If a follower is following 8 articles of one writer it has to be compared to '1' in the count.
I hope this will be clear enough to understand what I tried to reach.
With kind regards,
Nicky
Using distinct:
public function countFollowers($user_id)
{
$select = $this->select()
->distinct()
->where('user_id = ?', $user_id);
$rowset = $this->fetchAll($select);
$rowCount = count($rowset);
return $rowCount;
}
EDIT: After edit in question to get count of followers of a user. You actually need to use group NOT distinct. I have tested the following query works to fetch the data to be count()ed,
SELECT * FROM followers WHERE user_id = 1 GROUP BY user_id,
follower_id
I have not tested the code, but something like this should work:
public function countFollowers($user_id)
{
$select = $this->select()
->where('user_id = ?', $user_id)
->group(array('user_id', 'follower_id'));
$rowset = $this->fetchAll($select);
$rowCount = count($rowset);
return $rowCount;
}
You can specify mysql functions in the 'from' function that makes up select query function. To use the from function you need to pass the table name as the first parameter, however passing $this (your table model class) works fine.
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT user_id'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
[edit]
Based on your edit, 'group' may also work for you:
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->where('user_id = ?', $user_id)
->group('user_id')
);
return count($rowset);
}
This will group all matching user_id into one record. So if a user is found, it will return 1, else 0.
Retrieving all the rows simply to get a count strikes me as overkill.
You can do a count using something like this:
$select = $db->select();
$select->from('testcount', new Zend_Db_Expr('COUNT(id)'))
->where('user_id = ?', $someUserId);
return $db->fetchOne($select);
don't write that :
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT user_id'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
But that :
public function countFollowers($user_id)
{
$rowset = $this->fetchAll(
$this->select()
->from($this, array('DISTINCT(user_id)'))
->where('user_id = ?', $user_id)
);
return count($rowset);
}
Else you will have an error wich looks like to Mysqli prepare error:
Unknown column 'repertoire.distinct idRepertoireParent' in 'field list'
Also we have one method from the official manual
Just use "distinct"
Build this query: SELECT DISTINCT p."product_name" FROM "products" AS p
$select = $db->select()
->distinct()
->from(array('p' => 'products'), 'product_name');
Today I tried DISTINCT in JOIN LEFT case and it doesn't work. But if you add a Group By to the DISTINCT column, it works fine.