how to get ->orderBy('holding' > 0) in laravel eloquent query? - laravel

I have a holding(inventory) field in my product table,
I want to get products first that have holding > 0 and on last the products with holding <= 0.
$products = Product::orderBy('holding' , 'desc')->orderBy('id' , 'desc')->paginate(27);
the above query has problem that sorting by 'holding' number, I want to sorting by id, and the product with holding <= 0 goes to last page of pagination.
thanks

->orderByRaw(
"CASE WHEN holding > 0 THEN 0 ELSE 1 END DESC"
)

You can create tow collections. First with holding >0 and then with holding <=0 and then merge both collections.
$products = Product::where('holding','>',0)->orderBy('id' , 'desc')->get();
$otherProducts = Product::where('holding','<=',0)->orderBy('id' , 'desc')->get();
$products->concat($otherProducts);
$products->paginate(27);

Related

how to make orderBy ignore value 0 in eloquent laravel

My problem is that I have my collection that has a position field and I want it to be sorted in ascending order, but the fields that have the value null or 0 by default are detected as smaller than those that have an index.
My question is how can I make orderBy ignore the value 0 or null.
$listing = Product::get();
$listing = $listing->orderBy('order','ASC');
You could use CASE in your orderBy as a hack to "ignore" 0 (place it last).
$listing = Product::query()
->orderByRaw('CASE WHEN "order" = 0 THEN 0 ELSE 1 END DESC, "order" ASC')
->get();
You can also split it if you prefer.
$listing = Product::query()
->orderByRaw('CASE WHEN "order" = 0 THEN 0 ELSE 1 END DESC')
->orderBy('order')
->get();
$listing = Product::query()
->orderByDesc(DB::raw('CASE WHEN "order" = 0 THEN 0 ELSE 1 END'))
->orderBy('order')
->get();
$listing = Product::orderByRaw('-order DESC')->get();
There is a minus sign before the column.
Instead of asc, we are now sorting as desc, this is because we have inverted the values in #2 and so the sorting must also be inverted now to get the right results.
this working fine for me.

Wrong total pagination with select distinct in Laravel 6

I use Laravel 6.12, I have this request :
$queryJob = DB::table('jobs as j')->join('job_translations as jt', 'j.id', 'jt.job_id')
->whereNull('j.deleted_at')
->whereNull('jt.deleted_at')
->select('j.id', 'j.short_name', 'j.status', DB::raw("case when j.short_name = '{$request->short_name}' then 0 else 1 end"))
->distinct();
$jobs = $queryJob->paginate($qtyItemsPerPage);
The results displays an error for the total :
The total = 3, but as you can see the data contains only 2 elements.
I read here that when using a distinct, I must be clear on which column the total must be calculated: distinct() with pagination() in laravel 5.2 not working
So I modified my query like that:
$jobs = $queryJob->paginate($qtyItemsPerPage, ['j.*']);
But without success, the total is still wrong.
Hoping that I don't misunderstand your DB and relations structure and purpose of your query perhaps this will avoid using distinct or groupBy altogether?
$shortname = $request->input('short_name');
$queryJob = Job::with('job_translations')->select('id','short_name',
'status', DB::raw("case when short_name = '" . $shortname . "'
then 0 else 1 end")
->paginate($qtyItemsPerPage);
Pagination can be easily manually added with skip and take in case you need to use groupBy
$queryJob->skip(($page - 1) * $qtyItemsPerPage)->take($qtyItemsPerPage)->get();
The solution for me was to pass a field name to the distinct() method.
With your example:
$queryJob = DB::table('jobs as j')
// joins, where and other chained methods go here
->distinct('j.id')
Solution taken from https://stackoverflow.com/a/69073801/3503615

Laravel: How to get duplicated records and group them together?

The code below is what I have to get all the duplicated products (by title) and group them together. It works perfectly fine. However, I so many records in my Products table and getting all of them causes a performance issue. Is there a way this could be optimised to avoid getting all records and group them in one query? Thank you.
$products = Product::all();
$groupsOfProducts = $products->groupBy('title');
$duplicatedProductsGrouped = [];
foreach($groupsOfProducts as $productGroup) {
$productIsDuplicated = $productGroup->count() > 1;
if($productIsDuplicated) {
$duplicatedProductsGrouped[] = $productGroup;
}
}
var_dump($duplicatedProductsGrouped);
You can use having in the group by:
Product::groupBy('title')->having(DB::raw('count(*)'), ">", "1")->select('title')->get()
And you will get the titles of the duplicates, then you can query the database with those titles
EDIT:
Please also try and see if this is faster
Product::getQuery()->whereIn('title', array_column( DB::select('select title from products group by title having count(*) > 1'), 'title'))->get();
with this line you will get ONLY the products that has a duplicate title, and so your Collection groupby should be faster to aggregate the records by the title
Let your database do the work. When you call Product::all(), you're getting every single record, then making PHP do the rest. Change your query to something like the following:
Product::selectRaw("title, COUNT(*) AS count")->groupBy("title")->get();
The result will be a Collection of Product instances with a title and count attribute, which you can access and determine duplicated ones:
$products = Product::selectRaw("title, COUNT(*) AS count")->groupBy("title")->get();
$duplicatedProducts = collect([]);
foreach($products AS $product){
if($product->count > 1){
$duplicatedProducts->push($product);
}
}
dd($duplicatedProducts);

Eloquent query with a RAW order by

I have a eloquent query to get list items.
This is based on the idea that the sort column would be filled in, but in some circumstances it is not.
If its the case then I would like to order by the name of the list.
More or less what I wrote bellow.
order by CASE WHEN trickysort IS NOT NULL THEN trickysort::text ELSE list_name END
Here is the original query.
$list = Table_Lists::with(["listItems" =>
function($query)
{
$query
->orderBy('trickysort', 'asc')
->with("sublist.listItems");
}
])
->where("list_name","=", $name)
->where("hos_id","=", $hos_id)->get()->first();
return $list ? $list->toArray() : null;
The table structure is as follows.
Parent table -> table_lists
related child table -> table_list_items
the child table items are the one I need sorting. ( trickysort else list_name )
I hope this makes sense.
Im was thinking kind of a RAW query bit in the ->orderBy section of the child table.

Query max Codeigniter

I have a query that result 2 data(s) with the same employee
$this->load->library('datatables');
$this->datatables->select('a.employee_id, a.name, b.employee_position');
->from('employee a')
->join('employee_position b','b.employee_id = .a.employee_id AND `b`.`deleted`=0 AND `c`.`date_start` <= "'.$now_date.'"','inner')
$data = $this->datatables->get_adata();
$aaData = $data->aaData;
I wan't only one data appear which is choosing the max data on date_start column, how to do it?
Add these two lines in your code:
$this->db->order_by('c.date_start', 'DESC');
$this->db->limit(1, 1);

Resources