skip duplicate data from database in laravel - laravel

I just want to skip duplicate data from database,My foreign key is repeating so I just want to skip duplicate entry and get latest only
My controller is like that
$old=DB::table('tabl-1')
->leftJoin('tbl-2','tabl1.id','=','tabl2.tabl1_id')
->whereDate('created_at','<' ,Carbon::today())
->select('tbl1.name as name','tbl1.class as class','tabl2.table1_id')
->distinct('tabl2.table1_id')
->get()
->toArray();

DB::table('first')->leftJoin('second', 'first.id', '=', 'second.first_id')
->whereDate('first.created_at', '<', Carbon::today())
->select('first.name as name', 'first.class as class', 'second.first_id')
->groupBy('second.first_id')->get()->toArray();
Try groupBy, since distinct() has no argument in there

Related

Select joined table with same column name but different value using eloquent

I'm trying to call 2 columns from 2 different tables. applicants.ic_no and agents.ic_no. It have different values.
Using the following codes only displayed only ic_no from agents.ic_no
$claimLists = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->where('claim_date', $cutt_off)
->groupBy('agents.id', 'claim_details.id', 'applicants.id')
->orderBy('agents.id')
->orderby('amount', 'desc')
->get();
How do i get both columns to display?
This is because, you have ic_no in both tables. By default MYSQL picks one of it to display, it is the same as having id in both tables and from your results, how would you know which table's ic_no you are accessing while they have the same name?
Alternatively you can use select and DB::raw to change the name of one of the ic_no fields, and similiarly for any other similiar fields. For example;
$claimLists = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->select('claim_details.*', DB::raw('agents.ic_no as agents_ic_no'), 'agents.XXX', 'agents.YYYY', 'applicants.XXX')
->where('claim_date', $cutt_off)
->groupBy('agents.id', 'claim_details.id', 'applicants.id')
->orderBy('agents.id')
->orderby('amount', 'desc')
->get();
instead of XXX and YYY, you can put the fields that you would like to get and you can get as many as you want or remove them, if you don't want to get any field from the second table, but the main thing here is you are access the agents.ic_no as agents_ic_no or whatever name you would like to give it.
I solve this issue by adding select to rename the conflict column name. So this is the code:
$processed = ClaimDetail::join('applicants', 'applicants.ic_no', '=', 'claim_details.ic_no')
->join('agents', 'agents.id', '=', 'claim_details.agent_id')
->select('*')
->selectRaw('applicants.ic_no as nokp, agents.ic_no as agic')
->where('claim_details.agent_id',$agent->id)
->orderBy('claim_details.claimable', 'desc')
->orderby('claim_details.amount', 'desc')
->get();
Thanks guys for your time.

->first() return an empty array despite getting results

I have three tables I need to query.
Everything works fine so far, I get everything back I want, but as I just want to select the element in the array that holds the min price I want to ->first() on that one:
return Product::with(['price' => function($query) use ($today) {
$query->where(function ($subquery1) {
$subquery1-> *applying some filter here*
})->where(function ($timequery) use ($today){
$timequery->where('startingDate', '<=', $today)->where('endingDate', null)
->orWhere('startingDate', null)->where('endingDate', '<=', $today)
->orWhere('startingDate', '<=', $today)->where('endingDate', '>=', $today)
->orWhere('startingDate', null)->where('endingDate', null);
})->orderBy('price', 'asc');
}])->with('defaultPrice')->whereIn('id', $array)->get();
This works good so far. However, occassionally I get back 2 or more rows for the price relation (which is ok). However, I just want to select the first element in the array there.
When I put ->first() straight after ->orderBy('price', 'asc') I just get back an empty array.
When I put it before with('defaulPrice') I dont even get back my price relation
What am I actually missing here?
EDIT: Once I query for a single product with where('id', 'someId') it works, so this is down to whereIn... Anybody can explain me why and knows a way around this?

Pagination creates an error

Im trying to paginate a search to bring back pages of 18 items. Previously i had this code working code:
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('id')->orderBy('ratings_average', 'DESC');
I add on paginate to this as shown in the docs
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('id')->orderBy('ratings_average', 'DESC')->paginate(18);
And get an error
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in group statement is ambiguous
Any ideas on how to paginate the statement?
It's not neccesarily the pagination which is causing the issue, the error is caused by your group by.
You should place the table name / alias name prior to the id EG:
$productsQuery = Product::where('approved', '=', 1)->leftJoin('reviews', 'reviews.products_id', '=', 'products.id')->select('products.*', DB::raw('AVG(ratings) as ratings_average' ))->groupBy('product.id OR reviews.id')->orderBy('ratings_average', 'DESC');
Please see the ammended statement above, note that copy pasting it won't work, you'll see to change that groupby argument.
You should also visit the docs on Eloquent, you have approached this in a way where you're fighting laravel. I would suggest getting a tighter grip on the ORM used.
Good luck!
The error is pretty self explanatory here:
Column 'id' in group statement is ambiguous
so you need to make
`groupBy('id')`
more explicit, by telling which id (from which table, as each table used in your query features id column) you want to be used for grouping.

How to sort by primary table field and pivot in Eloquent?

Pivot table has one extra field: ordinal for sort order. How can I sort by ordinal and romance_color?
Inventory::where('item_id', '=', $itemId)
->with('size')
->orderBy('romance_color')
->get();
Documentation has the following example:
$users = User::with(array('posts' => function($query)
{
$query->orderBy('created_at', 'desc');
}))->get();
How can I first sort by field in primary table, and then by pivot table field? For example, can I sort by User added date, and then sort by post created date?
Can you suggest alternative solution in eloquent?
Thank you
I used simple join with eloquent:
Inventory::where('item_id', '=', '170')
->with('size', 'color', 'item.category')
->join('attribute_value_size_group as gr', 'gr.attribute_value_id', '=', 'size_id')
->orderBy('romance_color')
->orderBy('ordinal')
->select('inventory.*', 'gr.ordinal')
->get()->toArray();
You can use Query Builder:
For example:
$pivotTable= DB::table('pivot_table')->where('item_id', $itemID)->orderBy('romance_color')->get();
try this one.
$otherModelCollection = Inventory::where('item_id', '=', $itemId)->otherModel()
->orderBy('romance_color')
->orderBy('pivot_ordinal')
->get();
It is somewhat related to this.
http://laravel.io/forum/04-17-2014-order-by-pivot-table-attribute-in-eloquent

How to detach only the last record in the pivot table using detach() in Laravel 4?

If I do this:
return $this->roles()->detach($role);
all roles are removed.
How to limit that to only the last one?
You can do it without timestamps:
$lastRole = $user->roles()
->orderBy( $user->roles()->getTable() .'id', 'desc')
->first();
$user->roles()->detach($lastRole);
or with timestamps:
$lastRole = $user->roles()->latest()->first();
$user->roles()->detach($lastRole);
you may try this, I did not test it:
return $this->roles()->orderBy('id', 'desc')->first()->detach($role);
You can also order by timestamps, if no primary id is present, like this:
return $this->roles()->orderBy('created_at', 'desc')->first()->detach($role);
for this to work, you also have to edit your model, from the docs:
If you want your pivot table to have automatically maintained
created_at and updated_at timestamps, use the withTimestamps method on
the relationship definition:
return $this->belongsToMany('Role')->withTimestamps();
Another thing would be not to use model at all, because looking at this issue #3585 it is not that easy. Taylor closed it without a comment, so I assume it not get implemented. The solution should be (assuming you have timestamps columns migrated in the table). Tested code:
$last = DB::table($user->roles()->getTable())
->orderBy('created_at', 'desc')
->first();
DB::table($user->roles()->getTable())
->where('created_at', '=', $last->created_at)
->delete();

Resources