Laravel pagination not working with join where condtion - php

I am using laravel pagination for list. There is two tables lets say table1 & table2.
table2 id is primary key & used as foreign key in table1 t2_id
I want to get all unique t2_id but need to check is_deleted is not set for that id in table2.
I have written function in my model:
public function getDistinctIds() {
return DB::connection('pgsql')
->table('table1 AS t1')
->distinct()
->select('t1.t2_id')
->join('table2 AS t2', 't2.id', '=', 't1.t2_id')
->where('t2.is_deleted', '!=', 1)
->orWhereNull('t2.is_deleted')
->paginate(3);
}
This function will give me accurate result. But there is problem with pagination. There are 12 records in table1 getDistinctIds() gives only 4 record so there should be two pages but it is showing 4 pages. I think pagination is not taking where condition into consideration.
Please help thanks in advance!!

I got the solution instead of distinct()used groupBy(). Now it is working fine. :)
Referenced from laracast post : [L4.2] distinct() and pagination returns total number of results not distinct total

Related

Laravel Eloquent - get count non-repetitive columns according to another column

I have a table contains appointments, every appointment has provider_id and user_id foreign keys.
I want to get counts of non-repetitive users for each provider. Here is what I did,
return DB::table('appointments')
->where('provider_id', 1)
->groupBy('user_id')
->count();
It returns 2 when I have two appointments with the same provider_id and user_id, but what I want is 1.
How should I solve this?
Try adding ->distinct() and ->count('user_id') after the where
edit: Try this
return DB::table('appointments')
->where('provider_id', 1)
->distinct()
->count('provider_id');

Eloquent query to search over two tables

I am struggling with the following query, using Eloquent in Laravel 5.6.
I need to return all issues that have a tag_id of 5 assigned to them, where the project_id and item_id from the issues table matches the project_id and issue_id from my pivot table.
issues table:
issues_tags pivot table:
I have tried the following code, but it returns all issues from the issue table, however the expectation is 3 results.
Expected results
The results returned from the issues table should be ID 1, 4 and 5.
$issues = Issue::join('issues_tags', 'issues_tags.project_id', 'issues_tags.issue_id')->where('issues_tags.tag_id', 5)->select('issues.*')->get();
You need to specify the issues table instead of issues_tags on the join. A left join will also help reduce the results. Since you're joining on two different keys, you have to use a closure.
$issues = Issue::leftJoin('issues_tags', function($join) {
$join->on('issues.project_id', '=', 'issues_tags.project_id');
$join->on('issues.item_id', '=', 'issues_tags.issue_id');
})
->where('issues_tags.tag_id', 5)->select('issues.*')->get();
If the table is really supposed to match on project_id->project_id and issues.id -> issues_tags.issues_id, you can modify the 2nd join clause.

Laravel / MYSQL (Eloquent) - Querying large table

I am making an online directory, this directory contains businesses, this is how the current table structure is set out:
1) "Business"
ID (PK)
Name
Phone_Number
Email
2) Tags
id (PK)
tag
3) Business_tags
id (PK)
business_id (FK)
tag_id (FK)
There are over 9k rows inside of the business table, and over 84,269 rows and there are over 29k rows inside the ("Business_tags") table (As a business can have multiple tags).
Inside the business model, is the following:
public function tags()
{
return $this->belongsToMany('App\Tags');
}
The issue is when I am trying to do a search, so for example, let's say that someone wants to search for a "Chinese" then it's takes more time than it probably should to return a value. For example, I am using:
$business = Business::where(function ($business) use ($request) {
$business->whereHas('tags', function ($tag) use ($request) {
});
})->paginate(20);
Searching takes on average: 35 seconds to display the results.
Here is the raw sql:
select * from `businesses` where (exists (select * from `tags` inner join `business_tags` on `tags`.`id` = `business_tags`.`tags_id` where `business_tags`.`business_id` = `businesses`.`id` and `name` in ('chinese')))
This takes on average: 52.4s to run inside Sequel pro (Using the raw SQL statement)
Any ideas how I can improve the performance of this query so that it's a lot faster? I want to have this functionality, but the user is not going to wait this long for a response!
EDIT:
1 PRIMARY businesses NULL ALL NULL NULL NULL NULL 8373 100.00 Using where
2 DEPENDENT SUBQUERY business_tags NULL ALL NULL NULL NULL NULL 30312 10.00 Using where
2 DEPENDENT SUBQUERY tags NULL eq_ref PRIMARY PRIMARY 4 halalhands.business_tags.tags_id 1 10.00 Using where
You're over-complicating this, and not using eloquent relationships correctly. You should be using JOINs instead:
$businesses = Business::join('business_tags', 'business_tags.business_id', '=', 'business.id')
->join('tags', function($join) {
$join->on('business_tags.tag_id', '=', 'tags.id')
->where('tags.name', '=', 'chinese');
})->get();
Or in raw SQL:
SELECT *
FROM `business`
INNER JOIN `business_tags` ON `business_tags`.`business_id` = `business`.`id`
INNER JOIN `tags` ON `business_tags`.`tag_id` = `tags`.`id` AND `tags`.`name` = 'chinese'
(Note that you could put that tags.name = 'chinese' part in the WHERE clause and yield the same effect)
Your current query does an exists subquery to get all the records from the pivot table that match the criteria, then passing that back to the main query. It's an extra step, and it's unnatural.
Eloquent relationships are NOT for complex queries like this, but are rather there to provide additional, related information about a record without having to write another query manually.
For instance, if you want to view a business, you might query with() phone numbers and addresses from other tables. You might want to list out their tags, or sync() them. But eloquent does not build and filter queries, that's what query builder is for.
Let me know if you need more explanation.
As a lot of others are also going to tell you.
Have you run EXPLAIN on your query?
Have you added indexes to your tables?
Because even with the amount of data you have mentioned the query should have been faster than what you have reported.
Also see if a JOIN can work here and if faster?(just a thought)

Apply distinct on join query with CodeIgniter Query Builder

I am trying to make a query with codeigniters Query Builder
$this->db->select('*')
->from('users')
->join('user_to_group', 'users.id=user_to_group.user_id')
->where('user_to_group.group_id !=', $group->id);
Here in above code I'm trying to fetch records of users which are not in provided group. This query is working fine at the stage but sometimes it returns same record multiple times as a user can be part of multiple groups. So to overcome this problem I want to apply distinct to this query.
But I don't find the correct way to do it.
Please help..
You need to add group_by in query.
Write your query as below:-
$this->db->select('*')
->from('users')
->join('user_to_group', 'users.id=user_to_group.user_id')
->where('user_to_group.group_id !=', $group->id)
->group_by('users.id'); // add this line
Note : this query will work in only case if you use "user_to_group" table as multiple relation table mean user and group both tables id you used in this third table name "user_to_group".
Use group by if you need unique record on base of group_id
Try this :
$this->db->select('*')
->from('users')
->join('user_to_group', 'users.id=user_to_group.user_id')
->where('user_to_group.group_id !=', $group->id)
->group_by("user_to_group.group_id");
Because you will get multiple record when user is part of multiple group so you will use this to get groups unique records user vise or you will apply both group_id and user_id in group_by to get it unique from both field.

Laravel Eloquent Query to return count of grouped objects

I am working with laravel 5.1 and can't get this query to work. I have a places table, with a column county. I want to group by county and count how many of each country are in the table. I have a Place model for the places table but cannot figure out the query builder for this one.
A query that works is:
select county, count(*) from places group by county
Thanks in advance.
You may try this (Add a use statement for DB or use \DB):
$result = DB::table('places')
->select('county', DB::raw('count(*) as total'))
->groupBy('county')
->get();
Just from the top of my head does something like this work:
User::where('county')->count();

Categories