below is my code that duplicates database entries, what could the problem be?
When I try to trigger the end point that fetches employees it duplicates the entries multiple times
$all_employees = Employee::with([
'department',
'sub_department',
'first_supervisor',
'second_supervisor',
'reportingTo',
])
->select(
'employees.*',
'attendance_times.start_time as attendance_time',
'cities.city',
'countries.country',
'pay_frequencies.frequency as pay_frequency',
'duty_types.name as duty_type',
'rate_types.name as rate_type',
'positions.name as position_name',
'departments.department as sub_department',
'supervisors.name as supervisor_name'
)
->leftJoin('positions', function ($join) {
return $join->on('employees.position_id', '=', 'positions.id');
})
->leftJoin('countries', function ($join) {
return $join->on('employees.country_id', '=', 'countries.id');
})
->leftJoin('supervisors', function ($join) {
return $join->on('employees.first_supervisor_id', '=', 'supervisors.id');
})
->leftJoin('cities', function ($join) {
return $join->on('employees.city_id', '=', 'cities.id');
})
->leftJoin('attendance_times', function ($join) {
return $join->on('employees.attendance_time_id', '=', 'attendance_times.id');
})
->leftJoin('departments', function ($join) {
return $join->on('employees.sub_department_id', '=', 'departments.id');
})
->leftJoin('pay_frequencies', function ($join) {
return $join->on('employees.pay_frequency_id', '=', 'pay_frequencies.id');
})
->leftJoin('duty_types', function ($join) {
return $join->on('employees.duty_type_id', '=', 'duty_types.id');
})
->leftJoin('rate_types', function ($join) {
return $join->on('employees.rate_type', '=', 'rate_types.id');
})
->orderBy('employees.id', 'DESC')
->get();
return $this->customSuccessResponseWithPayload($all_employees);
Use with('Relation') while getting One to Many relation's data, because if you use leftJoin, you will get all the relation's data again.
Example:
Every Employee has many attendance_times, so if you create an SQL Query which gets all Employees and joined the attendance_times, the returned data will contain a duplicated EMP data every time it has attendance_times.
Basically use ->with('Relation').
Try to use the distinct with the query to fetch non-repetitive data.
DB::table('table')
->select('job_id')
->distinct()
->get();
It can be solved by adding the groupBy(employees.id) at the end of the query that's how I solved it.
Related
Hi I am trying to create a one on one messaging system on LARAVEL. It was working all fine until for some users it started showing different result then expected. And it happens only for some users.. What is wrong with this query
$id =$receiver->id;
$messages = Message::where(function ($query) use ($id) {
$query->where('user_id', '=', Auth::user()->id)
->where('receiver_id', '=', $id);
})->orWhere(function ($query) use ($id) {
$query->where('user_id', '=', $id)
->where('receiver_id', '=', Auth::user()->id);
})->get();
After I return $messages the result is like this...
Working Result: Messages are coming sequentially..
In View It shows like this..
Same Query Bad Result
In the view you can see date are not aligned in order
I really can't figure out what went wrong if you can help I would really appreciate..
Your date is casting as UTC with ISO-8601 format, but I think date is not related with your issue, if you are not ordering with timestamp.
I suggest you to use orderBy with id, it can solve your issue easily :
$messages = Message::where(function ($query) use ($id) {
$query->where('user_id', '=', Auth::user()->id)
->where('receiver_id', '=', $id);
})->orWhere(function ($query) use ($id) {
$query->where('user_id', '=', $id)
->where('receiver_id', '=', Auth::user()->id);
})
->orderBy('id', 'ASC')
->get();
I have this data
$result = DB::table('zone_regions')
->where('zone_regions.id', '=', $request->input('zone'))
->join('areas', function ($join) use($area) {
$join->on('zone_regions.id', '=', 'areas.zone_id')
->where('areas.id', '=', $area);
})
->join('hthree_regions', function ($join) use($city) {
$join->on('areas.id', '=', 'hthree_regions.area_id')
->where('hthree_regions.id', '=', $city);
})
->join('segments', function ($join) use($segment) {
$join->on('hthree_regions.id', '=', 'segments.hthree_id')
->where('segments.id', '=', $segment);
})
->join('links', function ($join) use($link) {
$join->on('segments.id', '=', 'links.segment_id')
->where('links.id', '=', $link);
})
->join('titik_closurs', function ($join) use($closure) {
$join->on('links.id', '=', 'titik_closurs.link_id')
->where('titik_closurs.id', '=', $closure);
})
// ->leftjoin('core_histories', 'titik_closurs.id', '=', 'core_histories.titik_id')
// ->select('titik_closurs.*', 'core_histories.*')
->groupBy('titik_closurs.id')
->get();
I want to add titik_closurs histories (core_histories) as an array into my returned data.
Sample data
Current data
This is what I have currently
data: [{...}]
0: {...}
id: 3
latitude: "6.2088000"
longitude: "106.8456000"
site_name: "98987454-54741115"
user_id: 1
zone_id: 2
And this is what I want to have
data: [{...}]
0: {...}
id: 3
latitude: "6.2088000"
longitude: "106.8456000"
site_name: "98987454-54741115"
user_id: 1
zone_id: 2
histories: [{......}]
histories: [{......}] array added to the results.
Note
This data (current data) are a bit messed up as is include data of all joined tables in my function, what I really need is just data of table titik_closurs and child of it table core_histories the rest aren't really useful for me in this case.
Sample of final data I wish to have:
data: [{...}]
0: {...}
// just data of `titik_closurs` exclude data of `zone_regions, areas, hthree_regions` etc.
id: 3
latitude: "6.2088000"
longitude: "106.8456000"
site_name: "98987454-54741115"
histories: [{....}]
Any idea how to do that?
Update
If I change my query (last part) to something like this:
->join('titik_closurs', function ($join) use($closure) {
$join->on('links.id', '=', 'titik_closurs.link_id')
->where('titik_closurs.id', '=', $closure)
->leftjoin('core_histories', function ($joinn) {
$joinn->on('titik_closurs.id', '=', 'core_histories.titik_id');
});
})
->groupBy('titik_closurs.id')
->get();
It does join core_histories to titik_closurs BUT,
It doesn't show them as child array
It only gets first core_histories not all.
Solved
I was playing with codes and came up with union solution then it led me to array_merge which fixed my issue.
So what I did basically was getting all histories in separate variable and push it into my default array.
//get histories
$histories = DB::table('core_histories')->where('titik_id', $closure)->get();
// default function
$result = DB::table('zone_regions')......
//merge them into one
$res = array_merge($result, ['histories' => $histories]);
Result
data: {
0: {...} // data
histories: [ // histories
0: {...}
1: {...}
]
}
Hope it help others as well.
For this particular situation you seem to have 3 (or 4?) related models. It's far easier (and much more readable) to define them as relationships and then do a nested retrieval with aggregation say:
$zone = Zone::with('region.segment.link.titik')
->where('id', $request->input('zone');
$titik = $zone->region->flatMap(function ($region) { return $region->segment })
->flatMap(function ($segment) { return $segment->link })
->flatMap(function ($link) { return $segment->titik });
What could also work (with yout current approach):
$result = DB::table('zone_regions')
->where('zone_regions.id', '=', $request->input('zone'))
->join('areas', function ($join) use($area) {
$join->on('zone_regions.id', '=', 'areas.zone_id')
->where('areas.id', '=', $area);
})
->join('hthree_regions', function ($join) use($city) {
$join->on('areas.id', '=', 'hthree_regions.area_id')
->where('hthree_regions.id', '=', $city);
})
->join('segments', function ($join) use($segment) {
$join->on('hthree_regions.id', '=', 'segments.hthree_id')
->where('segments.id', '=', $segment);
})
->join('links', function ($join) use($link) {
$join->on('segments.id', '=', 'links.segment_id')
->where('links.id', '=', $link);
})
->join('titik_closurs', function ($join) use($closure) {
$join->on('links.id', '=', 'titik_closurs.link_id')
->where('titik_closurs.id', '=', $closure);
})
// ->leftjoin('core_histories', 'titik_closurs.id', '=', 'core_histories.titik_id')
// ->select('titik_closurs.*', 'core_histories.*')
->get()
->groupBy('titik_closurs.id'); // Note the order change
This will use the collection's groupBy rather than the SQL GROUP BY (which does not provide any groups to the result)
You can do this with nested relationship. If you have model for each table its easier for you. see below code:
ZoneRegion Model:
public function area() {
return $this->belongsTo(Area::class);
}
in Area model:
public function hthree() {
return $this->belongsTo(HthreeRegions::class);
}
and so on...
when you want to use and append array as you want you can do:
ZoneRegion::where('your condition')->with('area.hthree.segments.etc')->get();
Maybe my relationship is wrong because I don't know exactly what your relationship is like, and if you give an example or tell the relationship, maybe I can answer better.
But in the end, this method simply eliminates your need.
Hope it help
I got this query, it fetch results from my database, based on relationships.
The query works fine, but it grabs the first entry from the database/table and not the first value of the array.
How can I fix that?
$motor = Motor::query()
->where([
['effect_id', '=', $request->effect_id],
['poles', '=', $request->poles],
['voltage_id', '=', $request->voltage_id],
['active', '=', 1],
])
->whereHas('MotorSize', function (Builder $query) {
$query->whereIn('mounting', ['B5', 'B14', 'B34', 'B35']);
})
->firstOrFail();
I have tried different things, such as:
Adding the orderBy to the Motor model and created a "priority" field in my database, giving each a number between 1 and 100:
(i actually thought this would work, but it still grabs the first entry from the table)
public function MotorSize()
{
return $this->belongsTo('App\MotorSize')->orderBy('priority', 'ASC');
}
I also tried something like this, but it's a mess and never got it to work:
$query->where(function ($query) {
$query->where('mounting', 'like', 'B5');
})
->orWhere(function($query) {
$query->where('mounting', 'like', 'B14');
})
->orWhere(function($query) {
$query->where('mounting', 'like', 'B34');
})
->orWhere(function($query) {
$query->where('mounting', 'like', 'B35');
});
Any suggestions will be welcome :)
My tables looks like this
area_trip
|id|dispatch_id|trip_id|status|
equipment_trip
|equipment_id|trips_id|dispatch_id|
trips
|id|dispatch_id|status
I am trying to pass collection to my resource. Can someone check my query and tell me what I am doing wrong as following query returning all the data matches dispatch_id whether it matches equipment_id or not. Btw I am new to laravel.
return
Resources::collection(
area_trip::where('dispatch_id', $request->dispatch_id)
->where('status', 1)
->orWhere('status', 9)
->whereHas('equipment_trip', function($query) use ($request) {
$query->where('equipment_trip.equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());
Here is the relationship set up in area_trip model
public function equipment_trip()
{
return $this->belongsTo(equipment_trip::class, 'trip_id', 'trips_id');
}
I believe your whereHas sub query is incorrect also instead of where and orWhere use where in and you can define all statuses necessary, try this:
Resource::collection(area_trip::where('dispatch_id', $request>dispatch_id)
->whereIn('status', [1, 9])
->whereHas('equipment_trip', function($query) use ($request) {
return $query->where('equipment_id', '=', $request->equipment_id);
})
->with(['equipment_trip', 'createdBy', 'updatedBy', 'area', 'trips'])
->orderBy('tripStartDate', 'ASC')
->orderBy('status', 'ASC')
->get());
I have a question about inner joins with multiple on values.
I did build my code like this in laravel.
public function scopeShops($query) {
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
// $join->on('kg_shops.active', '=', "1"); // WRONG
// EDITED ON 28-04-2014
$join->on('kg_shops.active', '=', DB::raw("1"));
});
}
Only problem is, it gives this outcome:
Column not found: 1054 Unknown column '1' in 'on clause' (SQL: select `kg_feeds`.* from `kg_feeds` inner join `kg_shops` on `kg_shops`.`id` = `kg_
feeds`.`shop_id` and `kg_shops`.`active` = `1`) (Bindings: array ( ))
As you can see, the multiple conditions in the join go fine, but it thinks the 1 is a column instead of a string. Is this even possible, or do I have to fix it in the where.
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
})
->select('required column names')
->where('kg_shops.active', 1)
->get();
You can see the following code to solved the problem
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
$join->where('kg_shops.active','=', 1);
});
Or another way to solved it
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
$join->on('kg_shops.active','=', DB::raw('1'));
});
//You may use this example. Might be help you...
$user = User::select("users.*","items.id as itemId","jobs.id as jobId")
->join("items","items.user_id","=","users.id")
->join("jobs",function($join){
$join->on("jobs.user_id","=","users.id")
->on("jobs.item_id","=","items.id");
})
->get();
print_r($user);
Because you did it in such a way that it thinks both are join conditions in your code given below:
public function scopeShops($query) {
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
$join->on('kg_shops.active', '=', "1");
});
}
So,you should remove the second line:
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id');
});
Now, you should add a where clause and it should be like this:
return $query->join('kg_shops', function($join)
{
$join->on('kg_shops.id', '=', 'kg_feeds.shop_id')->where('kg_shops.active', 1);
})->get();
You can simply add multiple conditions by adding them as where() inside the join closure
->leftJoin('table2 AS b', function($join){
$join->on('a.field1', '=', 'b.field2')
->where('b.field3', '=', true)
->where('b.field4', '=', '1');
})
More with where in (list_of_items):
$linkIds = $user->links()->pluck('id')->toArray();
$tags = Tag::query()
->join('link_tag', function (JoinClause $join) use ($linkIds) {
$joinClause = $join->on('tags.id', '=', 'link_tag.tag_id');
$joinClause->on('link_tag.link_id', 'in', $linkIds ?: [-1], 'and', true);
})
->groupBy('link_tag.tag_id')
->get();
return $tags;
Hope it helpful ;)
This is not politically correct but works
->leftJoin("players as p","n.item_id", "=", DB::raw("p.id_player and n.type='player'"))