Where not Exists en Laravel - mysql

Could anybody tell me what error I might have in my laravel query, basically what I want is to list the records of a table whose id is not related in another table. I did it in Mysql with this query: SELECT * FROM item WHERE NOT EXISTS (SELECT null FROM qualifications WHERE grades.item_id = item.id AND qualifications.user_id = 2);
but now I need to do this same query in laravel, I tried it this way:
codigo
and what I get is this syntax error that I do not know how to solve anymore:
error
I am very grateful to anyone who can tell me what I am doing wrong, or in what form I make that query in Laravel.

You can also rewrite your query as left join like
SELECT i.*
FROM item i
LEFT JOIN qualifications q ON q.item_id = i.id AND q.user_id = 2
WHERE q.item_id IS NULL
In query builder you can write it as
DB::table('item as i')
->select('i.*')
->leftJoin('qualifications as q', function ($join) use($user_id) {
$join->on('q.item_id', '=', 'i.id')
->on('q.user_id', '=', $user_id);
})
->whereNull('q.item_id')
->get();
Another approach which i suggest you to go with, is setup your relations and models and do it with eloquent way
class Item extends Model
{
public function qualifications()
{
return $this->hasMany(\App\Models\Qualification::class, 'item_id');
}
}
class Qualification extends Model
{
public function qualifications()
{
return $this->belongsTo(Item::class, 'item_id');
}
}
And then you can use Querying Relationship Absence
Item::whereDoesntHave('qualifications', function ($query) use($user_id) {
$query->where('user_id', '=', $user_id);
})->get();

Related

Need to convert a query into Eloquent Model laravel

I have a query of MySQL but I need to convert it into an eloquent model laravel 8. The query is given below,
$query = "SELECT group_id FROM `chat_histories` join chat_group on chat_group.id = chat_histories.group_id where chat_group.is_group = 1 and chat_histories.created_at BETWEEN '$startDate' and '$endDate' and chat_histories.deleted_at is null group by group_id";
$query = "select count(group_id) as total_chat_thread from ($query) total_chat";
DB::select($query);
So far i have done this,
ChatHistory::leftJoin('chat_group', 'chat_group.id', '=', 'chat_histories.group_id')
->selectRaw('count(*) as totals')
->where('chat_group.is_group', 1)
->whereBetween('chat_histories.created_at', [$startDate, $endDate])
->groupBy('chat_histories.group_id')
->count('totals');
But this returns a list, but I need that count of the list. That means it's showing 22 rows, I need that 22 as return.
My Model ChatHistory relation with ChatGroup
public function chatGroup() {
return $this->belongsTo(ChatGroup::class, 'group_id', 'id');
}
My Model ChatGroup relation with ChatHistory
public function chatHistory() {
return $this->hasMany(ChatHistory::class,'group_id','id');
}
Please help to convert it into an eloquent model query
Thanks in advance.
If you have the model Group with a relation history hasMany. it should be like this.
$groupCount = ChatGroup::whereHas('chatHistory', function ($historyQB) use($startDate,$endDate) {
$historyQB->whereBetween('created_at', [$startDate, $endDate])
->whereNull('deleted_at');
})->count();
You dont need the whereNull, if the model ChatHistory has softDelete enabled.
Maybe you should consider using Models, it would be much easier/cleaner
Something like that should work
DB::table('chat_histories')->select('group_id')->join('chat_group', 'chat_group.id', 'chat_histories.group_id')->where('chat_groups.is_group', 1)->whereBetween('chat_histories.created_at', $startDate, $endDate)->whereNull('chat_histories.deleted_at')->groupBy('group_id')->count();

how to to make eloquent scope with whereHas like sql query below?

how to to make eloquent scope with whereHas like sql query below
table Property(id, title, slug, category_id, location_id,image)
table Category(id, name, slug)
table City ( id, name, slug)
The simple sql query that i need
Select * from property
join category on property.category_id=category.id
join city on property.location_id = city.id
where category.name = $query and city.name=$query
I want to make the eloquent scope in the Property Model
This is easy with relationships.
Based on your query, let's say this is your Property model:
class Property extends Model
{
public function category()
{
return $this->belongsTo(Category::class);
}
public function city()
{
return $this->belongsTo(City::class, 'location_id');
}
Now I can write my Eloquent query like this:
$query = 'Example';
$properties = Property::where('name', $query)
->whereHas('category', function (Builder $builder) use ($query) {
$builder->where('name', $query);
})->get();
Please note that Builder is imported from Illuminate\Database\Eloquent\Builder. You can also add with('category', 'city') to the query above in order to eager load those relationships.

Laravel: get models if count of relation has some condition

I have User and UserComplains Models.
I like to retrieve users that have UserComplains more than 2 times in the last 24 hours.
users:
id
user_complains:
complained_id ->ref-> users.id
created_at
this is what I tried and it is working:
$users = User::select('users.*')->join('user_complains' , 'users.id' , '=' , 'user_complains.complained_id')
->whereRaw("(
select count(*) from `user_complains`
where `user_complains`.`complained_id` = `users`.`id`
and `user_complains`.`created_at` > ?) >= ?" , [now()->subHours(24), 2])
->groupBy("users.id")
->get();
the above code is fine and is working, but I wonder is there a better way to do that?!
For something like this you can use whereHas(). :
$users = User::whereHas('*relationship*', function ($query) {
$query->where('created_at', '>=', now()->subDay(1));
}, '>', 2)->get();
As mentioned in the documentation, you can pass additional checks as the 3rd and 4th param so in this case you want to say where the user has more that 2 user_complains.
NB You will need to replace *relationship* with the actual name of the relationship.
You can do the following:
User::whereHas('complaints', function($query) {
$query->where('created_at', '>=', '2020-04-26');
}, '>', 2)->get();
In order for this to work though you need to have set up a relationship between your User and UserComplaint models.
class User extends Model
{
public function complaints()
{
return $this->hasMany(UserComplaint:class);
}
}

Issue with eloquent Laravel

I have a problem with Eloquent, how to show the sum of products with 0 purchase price.
my model invoice and method products
public function products()
{
return $this->belongsToMany(Product::class)->withPivot('quantity', 'product_name', 'net_unit_price', 'gross_unit_price', 'purchase_price');
}
my model products and method invoice
public function invoices()
{
return $this->belongsToMany(Invoice::class);
}
and I need sum - net_unit_price from invoices sold in this month for eg
$sellMonthReplace = $user->invoices()
->with(['products' => function ($query) {
$query->wherePivot('purchase_price', '=', '0');
}])
->whereNull('parent_id')
->where('incoming', '=', '0')
->whereNull('is_proforma')
->where('sell_date', '>', $now->format('Y-m-01'))
->sum('net_value');
but this isn't working.
this below work well but is raw SQL and I don`t know how do it in eloquent
select SUM(invoice_product.net_unit_price*invoice_product.quantity)
from homestead.invoices
join homestead.invoice_product on invoice_product.invoice_id = invoices.id
where invoices.sell_date > 2019-03-01
and invoices.incoming = 0
and invoices.parent_id is null
and invoices.is_proforma is null
and invoice_product.`purchase_price` = 0
anybody could help me? thank you in advance
Did you try to cut your query short to make sure that your relations are working?
Also is the $user variable filled properly ?
What does a dump of the $sellMonthReplace return to you?

Select SUM from subquery while using whereHas in Laravel

I have 2 tables, customers and customer_invoices, and I want to get all the customers with a condition on their invoices, and select specific columns (customers.id, customers.last_name, and the sum of the total_price of the invoices for each customer), I have this query :
$result = Customer::whereHas('customerInvoices', function(Builder $q) {
$q->where('customer_invoices.status', 1);
})->select([
'customers.id',
'customers.last_name',
\DB::raw('SUM(customer_invoices.total_price) as sum')
])->get();
customerInvoices is the relation :
public function customerInvoices() {
return $this->hasMany(CustomerInvoice::class);
}
I want to use subqueries instead of joins, so here I can't select this \DB::raw('SUM(customer_invoices.total_price) as sum'), or else I get this error of course :
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'customer_invoices.total_price' in 'field list' (SQL: select `customers`.`id`, `customers`.`last_name`, SUM(customer_invoices.total_price) as sum from `customers` where exists (select * from `customer_invoices` where `customers`.`id` = `customer_invoices`.`customer_id` and `customer_invoices`.`status` = 1))"
How can I achieve this without using joins ?
You can use withCount() to get sum from related model as
$result = Customer::select([
'customers.id',
'customers.last_name'
])->withCount([
'customerInvoices as invoice_sum' => function($query) {
$query->select(DB::raw('SUM(total_price)'));
}
])->whereHas('customerInvoices', function(Builder $q) {
$q->where('customer_invoices.status', 1);
})->get();
Another approach to get sum, you can define a hasOne() relation in your Customer model like
public function invoice_sum()
{
return $this->hasOne(CustomerInvoice::class)
->select('customer_id',
DB::raw('sum(total_price)')
)->groupBy('customer_id');
}
And in query builder
$result = Customer::select([
'customers.id',
'customers.last_name',
])->with('invoice_sum')
->whereHas('customerInvoices', function(Builder $q) {
$q->where('customer_invoices.status', 1);
})->get();
As per Eloquent : withCount() overrides the $columns on get() issue first put select() mehtod and then use with() function