Prevent getting a duppicate data from the database in CodeIgniter - php

I'm trying to get data from the database filtered by some categories
This is my code in CodeIgniter
$this->db
->select('*')
->from($this->table)
->join('sites','sites.id = categories_by_site.site_id')
->where('categories_by_site.category_id', $categories[0])
->or_where('categories_by_site.category_id', $categories[1])
->order_by('id', 'ASC')
->get()
->result();
I simplify my code for the sake of this question, the above query take the categories as a search filter and used it to get result from the database.
There can be many categories filter to search at the same time, that's why I am using or_where() method.
The problem with this, when I got the result data, it has duplicate row of entries in object array.
Anyone can suggest how to prevent from getting a duppicate data from the database using above query?
Thanks

You can use group_by to solve this issue
Replace your code with
$this->db
->select('*')
->from($this->table)
->join('sites','sites.id = categories_by_site.site_id')
->where('categories_by_site.category_id', $categories[0])
->or_where('categories_by_site.category_id', $categories[1])
->order_by('id', 'ASC')
->group_by('categories_by_site.category_id')
->get()
->result();

You can eleminate duplicate values using distinct or group by
As you select all fields a group by is better in my opinion. Example to group by category_id
$this->db->group_by('category_id');

Related

How to get 'most commented posts' in Doctrine?

I have Post entity. Post entity have one Category, many Tags and many Comments.
How to get 'most commented posts' ordered by most commented?
When I am doing this:
$query = $this->createQueryBuilder('post')
->addSelect('COUNT(comments.id) AS HIDDEN comments_num')
->innerJoin('post.comments', 'comments')
->groupBy('post.id')
->orderBy('comments_num', 'DESC')
->addOrderBy('post.created', 'DESC')
->getQuery()
;
it is working but Doctrine makes so many queries, but the problem is the more comments the more queries *times something... It cant be that way. On the page with this query results I have 71 queries and the number of them grows with commented posts number.
When I am doing the same but adding left joining and selecting category, tags and comments there... queries number is low and independent from comments number but when I pass that query to Paginator it gets kind of empty pages after few pages with results...
$query = $this->createQueryBuilder('post')
->addSelect('category, tags, comments')
->addSelect('COUNT(c) AS HIDDEN comments_num')
->innerJoin('post.comments', 'c')
->innerJoin('post.comments', 'comments')
->leftJoin('post.category', 'category')
->leftJoin('post.tags', 'tags')
->groupBy('post.id')
->addGroupBy('tags.id')
->addGroupBy('comments.id')
->orderBy('comments_num', 'DESC')
->addOrderBy('post.created', 'DESC')
->getQuery()
;
query will be passed to Paginator so it must be build in DQL or using QueryBuilder.
edit:
I think there is a bug in Paginator, because... When I dump that second query results I am getting good results in array collection of 12. But when I pass that query to Paginator and then call Paginator.count() I get results: 55 :D when there are 44 posts in test database :)
In The first moment Write your query just with SQL, after do you can execute pure SQL in doctrine.
After you try convert your SQL for DQL

Laravel where with 2 tables

I'm trying to check the another table to remove the matches from the results but unable to figure this out.
$value = people::select(array('people.blog_id'))
->join('blocks', 'people.user_id', '=', 'blocks.blocker')
->where('people.user_id', $user->id)
->where('blocks.blocker', '!=', 'people.user_id')
->get()
->toArray();
What I am trying to achieve, is to strip away the results when getting user_id from people where blocker is found as well in the blocks table, but the following returns an empty array.
As per laravel doc
You may use the table method on the DB facade to begin a query. The table method returns a fluent query builder instance for the given table, allowing you to chain more constraints onto the query and then finally get the results using the get method.
Change your query statement like bellow-
$articles = DB::table('people')
->join('blocks', 'people.user_id', '=', 'blocks.blocker')
->where('blocks.blocker', '<>', 'people.user_id')
->select('people.blog_id')
->get();
I think you should use right join here instead of simple join,
You can do it like.
$value = people::select(array('people.blog_id'))
->join('blocks', 'people.user_id', '=', 'blocks.blocker', 'right')
->where('people.user_id', $user->id)
->get()->toArray();
Please notice the fourth parameter in the join statement, this will include only the results where blocks will find.
Hope this will help

Laravel Eloquent join table and count related

I have two tables, categories and product. I'm trying to add a query to count products of each category without foreach of the categories. I reached the query below:
DB::table('categories')->leftJoin('product', 'categories.id', '=','categpry_id')
->selectRaw('categories.*, count(product.id) as Count')
->where('product.status',1)
->groupBy('categories.id')
->get();
But the problem I'm facing is when a category doesn't have products it's not showing. I want to show the categories with no product with 0 product in the array.
You can use Eloquent's withCount method:
$categories = Category::withCount('products')->get();
Each $category will have a products_count attribute.
I'm pretty sure you can use rightJoin for this.
Not 100% sure though.
The first line in your code is bad in a few ways
'categories.id', '=','categpry_id')
You have a typo
Add the table also 'categories.id', '=', 'products.category_id'
If you're using models, which you should be... #DigitalDrifter has an "Eloquent" solution.
Two asides
I would refrain from using mysql reserved words in your aliases. COUNT(product.id) AS product_count instead.
You can minimize your raw statement with an array passed to select instead.
Here is what I would use
Categories::leftJoin(Product::class, 'product.category_id', '=', 'categories.id')
->select([
'categories.*',
DB::raw('COUNT(products.id) AS product_count')
])
->where('product.status', 1)
->groupBy('categories.id')
->get();
TIL.
Model::withCount('relation') that is pretty darn cool too.

Laravel Query Buider Group By Not Getting All The Records

I am trying to get the data using groupBy on type field from my transaction table. I am using this query
DB::table($this->table)
->select()
->whereRaw($where['rawQuery'], isset($where['bindParams']) ? $where['bindParams'] : array())
->groupBy('type')
->get();
But it is not giving the complete records. There are more than 10 records in my table. But it is giving me only two. One for type=1 and another for type=2. It is selecting only on record from each type. I am expecting that i will get all the transactions based on condition grouped in two result set. Anyone know why it is happening?
Try to call Collection groupBy instead. Just put groupBy after get(). It should work.
DB::table($this->table)
->select()
->whereRaw($where['rawQuery'], isset($where['bindParams']) ? $where['bindParams'] : array())
->get()
->groupBy('type');
Faq::where('type','host')->get()->groupBy('category');

how to group by in db query builder to get the unique value?

Can someone help me to convert the below mysql to laravel db query builder or eloquent?Here is my mysql
SELECT max(created_at), jobseeker_id,call_reason,type_of_call
FROM calllogs
GROUP BY jobseeker_id
ORDER BY created_at DESC;
Here is my tries, but no luck yet.
$jobseekers =DB::table('calllogs')
->select(DB::raw("max('created_at'),jobseeker_id"))
->groupBy('jobseeker_id')
->orderBy('created_at','desc')
->get();
dd($jobseekers);
Please help me out.
$jobseekers =DB::table('calllogs')
->select(DB::raw("max(created_at),jobseeker_id"))
->groupBy('jobseeker_id')
->orderBy('created_at','desc')
->get();
Try with this code.
Only delete ' ' in max.
It will work well.
DB::table(calllogs)
->select(DB::raw('max(created_at) as max_created_at'),
'jobseeker_id','call_reason','type_of_call')
->groupBy('jobseeker_id')
->orderBy('max_created_at', 'DESC')
->get(); =>As a array.
->first(); => As a object.
Additionally, If you are using table joins see below.
->join('table_1','table_1.id','=','table_2.table_1_id')
->leftjoin('table_1','table_1.id','=','table_2.table_1_id')
->rightjoin('table_1','table_1.id','=','table_2.table_1_id')
ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'myapp.calllogs.created_at'
Two solution for that error
1.In config/database.php file make sql strict mode to false.
(or)
2. IN groupBy Clause add all your table colums.
example:
->groupBy('jobseeker_id','jobseeker_name','jobseeker_email')

Categories