Laravel ordering and limit results of a left join - laravel

One to many relationships, each product has many prices
table products
id | name | slug | created_at | update_at
table prices
id | product_id | title | price | link
I want to get the data limit of product limit 20 table and order created_at and each product get the lowest price, order column price. I want to use the query builder.
i tried
$products = DB::table('products')
->leftJoin('prices', 'products.id', '=', 'prices.product_id')
->select('products.id', 'products.name')->distinct()
->selectRaw('max(prices.price) as price')
->groupby('products.id')
->orderby('products.updated_at')
->get();
but it get all products and table prices order column id

You can use Eloquent Like This
public function price() {
return $this->hasMany('App\model\Prices' , 'product_id' ,'id');
}
and get like this , It will give you the mapped price only for your specific product
$product = Product::with('price')
->where(do the stuffs)
->orderBy(do the stuffs)
->get();
Or you can use the callback as well in with()

Related

Laravel - Eloquent select with count some related data

I have following query:
Product::where('shop_id', $shop->id)->with('orderItems')->get()
Product: id | title
OrderItem: id | product_id | sell_price | sold_quantity | sold_date
And i would like to count total income (what is sell_price * sold_quantity) and the same for last 30 days.
How to get all products for shop and calculate that data for every single one.
Thank you.
DB::table('products as p')
->join('orderItems as oi','p.id','oi.product_id')
->where('p.shop_id', $shop->id)
->whereDate('created_at', '>=', Carbon::now()->subDays(30)->toDateTimeString())
->selectRaw('p.id,p.name, sum(oi.sell_price * oi.sold_quantity) as total,
(select sum(sell_price * sold_quantity) from orderItems
where product_id = p.id) as grand_total')
->groupByRaw('p.id,p.name')
->get();

Laravel leftJoin only last record of right table and order by it

I have two tables. 1) products 2) prices
-------------------------
- products -
-------------------------
- id | int -
- name | varchar -
- created_at | datetime -
- updated_at | datetime -
-------------------------
----------------------------
- prices -
----------------------------
- id | int -
- product_id | int -
- sale_price | int -
- regular_price | int -
- created_at | datetime -
- updated_at | datetime -
-----------------------------
I want to search through products and get the last price of each product from prices table. I use this :
class Product extends Model
{
public function lastPrice()
{
return $this->hasOne(Price::class)->orderBy('id', 'DESC');
}
}
And I get products list with the last price using :
$products=Product::with('lastPrice')->paginate(9);
My question is: I want to order the result by highest/lower price. How I will do that?
You can select latest row from prices table along with product data there are 2 ways which I can think of right now as
// Approach 1
Product::join('prices as a', 'products.id', '=', 'a.product_id')
->leftJoin('prices as a1', function ($join) {
$join->on('a.product_id', '=', 'a1.product_id')
->whereRaw(DB::raw('a.id < a1.id'));
})
->whereNull('a1.product_id')
->select('products.*', 'a.*')
->orderBy('sale_price','desc')
->orderBy('regular_price','desc')
->get();
// Approach 2 with whereExists
Product::join('prices as a', 'products.id', '=', 'a.product_id')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('prices as b')
->whereRaw(DB::raw('a.product_id = b.product_id'))
->havingRaw('max(b.id) = a.id');
})
->select('products.*', 'a.*')
->orderBy('sale_price','desc')
->orderBy('regular_price','desc')
->get();
I believe using laravel 6 or above you can use correlated sub queries in addSelect() clause as
Product::addSelect(['latest_price' =>
Price::select('price')
->whereColumn('product_id', 'products.id')
->orderBy('id', 'desc')
->limit(1)
])->orderBy('latest_price','desc')
->paginate(9);
So from above we will get products data along with latest price column from database so you can apply sorting on latest_price
Edit If you have limited columns to select like sale_price you can add another sub query but if you want to select whole row from price table then see another approach using join/exists
Product::addSelect(['sale_price' =>
Price::select('sale_price')
->whereColumn('product_id', 'products.id')
->orderBy('id', 'desc')
->limit(1),
'regular_price' =>
Price::select('regular_price')
->whereColumn('product_id', 'products.id')
->orderBy('id', 'desc')
->limit(1),
])->orderBy('sale_price','desc')
->orderBy('regular_price','desc')
->get();

Eloquent query distinct sub id

I have these models
I want to make a query that shows me all the products whose stock quantity> 0 and that does not repeat the products.
My query:
$stock_products_limit = Stock::distinct('product_id')->where('quantity', '!=', 0)->get();
This would be much easier using a size chart relating it to stocks ... but for now I don't have it
I need the model to return me, and then do a foreach:
#foreach($stock_products_limit as $stock_product)
#foreach($stock_product->product->product_images as $i=>$product_image)
...
#endforeach
...
#enforeach
In my models I have the hasMany and belongsTo relations made
How could I make the query? I've been trying the distinct, group by ... but nothing works for me. It only removes the ones with quantity 0 and repeats the product ID ...
Example of the query I want:
SELECT DISTINCT(stocks.product_id)
FROM stocks
INNER JOIN products ON stocks.product_id = products.id
WHERE quantity != 0
ORDER BY product_id
LIMIT 10;
Another example query (but LIMIT doesn't work with IN)
SELECT * from products where id in (SELECT DISTINCT(product_id)
FROM stocks
INNER JOIN products ON stocks.product_id = products.id
WHERE quantity != 0
ORDER BY product_id)
Instead of making the Stock model as the starting point, you might want to use the Product model. Then you don't even have to think about using DISTINCT. Let's use whereHas
return Product::whereHas('stocks', function ($query) {
$query->where('quantity', '>', 0);
})
->limit(10)
->get();

Laravel Eloquent order by using relation data

I have the following 2 tables:
Cars
----
id | created_at
and
Repaired
id | cars_id | updated_at
I want to display all cars, ordered by created_at desc, BUT also ordered by updated_at from the Repaired pivot table. Repaired can have many entries of specific cars_id.
So if carA is created_at 2017-02-20, and carB is created_at 2016-01-10, but the updated_at in Repaired for carB is on 2017-02-22, i want to display carB BEFORE carA, because the relation is "newer".
I also don't want do load the data from the relation table.
I tried the follwing:
$cars = $model->load(['repaired' => function($query) {
return $query->orderBy('updated_at', 'desc');
}])->orderBy('created_at', 'desc');
and
$model->join('repaired', 'repaired.cars_id', '=', 'cars.id')
->orderBy('repaired.updated_at', 'desc')
->orderBy('cars.created_at', 'desc')
->select('cars.*');
^ this query return all items from the Repaired table, even if the updated_at field is NULL. And i can't group them.
You can use the touch parent timestamps feature in Eloquent, to update the updated_at for the car, every time Repaired is updated.
In your Repaired model just add this line:
protected $touches = ['car'];
This is assuming your relation method is named car() of course.
Then you can do this:
Cars::orderBy('updated_at');
Every time a row in the Repaired table is added or updated, the car specified in the car relation will have its updated_at set to the same time. That way you can order by it.
$popular_posts = Post::withCount('favorite_to_users')
->orderBy('view_count', 'desc')
->orderBy('favorite_to_users_count', 'desc')
->take(5)->get();

How in query Eloquent specify condition with relations

I have 2 tables:
articles
id | title | category_id | created_at | updated_at |
and categories
id | name | descriptions | created_at | updated_at |
Relations : category hasMany-> articles and articles belongsTo -> category.
how simple way make query something like :
public functions getArticles ($category) {
$articles = Articles::where('category', '=', $category);
}
In documentations exist example with Id (http://laravel.com/docs/4.2/eloquent#one-to-many ) , but I want select articles, knowing name category.
How in query specify condition with relations ?
If exist such methods, please help me.
Thanks ;)
You can use whereHas method. Like:
$articles = Articles::whereHas('category', function($query)use($category){
$query->where('name', $category->name);
});
I suppose that should work. Or you can just create a scope and join categories table and then check by it.

Resources