How to write below query in Laravel - php

I have a table and there are two columns.
user_id
to_user_id
101
102
102
101
101
105
In the above table, 1 and 2 rows of users are like each other I want to remove 2 rows.
Here is my code.
$query = \App\Models\MyMatch::query();
$query->whereHas('users')->whereHas('tousers')
->select('my_matches.*')->distinct()
->where('user_id', '!=', 'to_user_id');
$records = $query->get();
In the above code, I got total 3 rows
I want only a total of 2 rows 1 and 3
So, how can I write a query for it

$records = \App\Models\MyMatch::whereHas('users')->whereHas('tousers')
->where(function($query) {
$query->where('user_id', '!=', 'to_user_id')
->orWhere(function($query) {
$query->where('user_id', '<', 'to_user_id');
});
})
->distinct()
->get();
or use a subquery :
$subquery = DB::table('my_matches')
->select('user_id', 'to_user_id')
->whereColumn('user_id', '>', 'to_user_id')
->toSql();
$records = \App\Models\MyMatch::whereHas('users')->whereHas('tousers')
->whereNotExists(function($query) use ($subquery) {
$query->select(DB::raw(1))
->from(DB::raw("($subquery) as sub"))
->whereRaw('my_matches.user_id = sub.to_user_id and my_matches.to_user_id = sub.user_id');
})
->get();

You can use
$query = \App\Models\MyMatch::query();
$query->whereHas('users')->whereHas('tousers')
->select('my_matches.*')
->where('user_id', '!=', 'to_user_id')
->groupBy('to_user_id')
->havingRaw('COUNT(*) = 1');
$records = $query->get();

Related

Laravel combined OR AND Solution

I need to do select as the following
select * from table where (x = 1 OR y = 1) AND starting_at < '2018-05-01'
How to do that please.
DB::table('tableName')
->where(function ($query) {
$query->where('x', '=', 1)
->orWhere('y', '=', '1');
})
->where('starting_at', '<', '2018-05-01')
->get();

laravel 5.2 nested Where clause

How to perform a where clause using laravel eloquent with the following query:
select * from stats where payed = 1 AND WHERE (user_id = 1 OR owner_id = 1)
I don't know how to modify this code for this:
$payouts = Stat::where('payed', '1')
->???(function ($query) {
$query->where('owner_id', Auth::user()->id)
->where('user_id', Auth::user()->id);
})->get();
Change like this
$payouts = Stat::where('payed', '1');
$payouts->where(function ($payouts) {
$payouts->where('owner_id', Auth::user()->id)
->orWhere('user_id', Auth::user()->id);
})->get();
Try this
$payouts = Stat::where('payed', '1')
->where(function ($query) {
$query->where('owner_id', Auth::user()->id)
->orwhere('user_id', Auth::user()->id);
})->get();
You're close, this should do the trick:
$payouts = Stat::where('payed', '1')
->where(function ($query) {
$query->where('owner_id', Auth::user()->id)
->orWhere('user_id', Auth::user()->id);
})->get();
This is looking for where payed = 1 AND (owner_id is the current user ID OR the user_id is the current user ID)

Laravel 4.2 - Select only rows where count of rows based on another query are 0

I want to set up scheduled emails for recommended oil changes. To do this, I need to select from a table of line items where the last oil change was over 3 months ago. I need a condition to ignore currently selected customer rows where an oil change was purchased under 3 months ago. How would I add this condition?
$search_term = 'oil change';
$date = new DateTime('-3 months');
$users = $this->prospectInstance->getDatabase()->table('LineItems')
->join('WorkOrder', 'WorkOrder.id', '=', 'LineItems.order_id')
->join('Customer', 'Customer.customer_id', '=', 'WorkOrder.customer_id')
->where('LineItems.line_type', 'like', "%$search_term%")
->where('WorkOrder.create_date', '<=', $date)
// this block produces errors
->whereNotIn('Customer.customer_id', function($query) use ($search_term, $date)
{
return $query->where('LineItems.line_type', 'like', "%$search_term%")
->join('WorkOrder', 'WorkOrder.id', '=', 'LineItems.order_id')
->join('Customer', 'Customer.customer_id', '=', 'WorkOrder.customer_id')
->where('WorkOrder.create_date', '>=', $date);
})
->orderBy('WorkOrder.create_date', 'DESC')
->groupBy('Customer.customer_id');
Table Structure:
LineItems
order_id
line_type
WorkOrder
id
customer_id
create_date
Customer
customer_id
Edit: I was able to use the advice below to use two separate queries to accomplish this, but I'd like to know if there is a single query I can create to accomplish the same result:
$search_term = 'oil change';
$date = new DateTime('-3 months');
$base_query = $this->prospectInstance->getDatabase()->table('LineItems')
->join('WorkOrder', 'WorkOrder.id', '=', 'LineItems.order_id')
->join('Customer', 'Customer.customer_id', '=', 'WorkOrder.customer_id')
->where('LineItems.line_type', 'like', "%$search_term%")
->orderBy('WorkOrder.create_date', 'desc')
->groupBy('Customer.customer_id');
$recent = clone $base_query;
$users = clone $base_query;
$recent->where('WorkOrder.create_date', '>', $date)
->select('Customer.customer_id');
$users->where('WorkOrder.create_date', '<=', $date)
->whereNotIn('Customer.customer_id', $recent->lists('customer_id'));
I think this would work but is obviously not tested:
$users = $this->prospectInstance->getDatabase()->table('Customer')
->join('WorkOrder', 'WorkOrder.customer_id', '=', 'Customer.customer_id')
->join('LineItems', 'LineItems.order_id', '=', 'WorkOrder.id')
->where('LineItems.line_type', 'like', "%$search_term%")
->whereNotIn('Customer.customer_id', function($query) use ($date, $search_term)
{
$query->select('Customer.customer_id')
->from('Customer')
->join('WorkOrder', 'Customer.customer_id', '=', 'WorkOrder.customer_id')
->join('LineItems', 'WorkOrder.id', '=', 'LineItems.order_id')
->where('WorkOrder.create_date', '>', $date)
->where('LineItems.line_type', 'like', "%$search_term%");
})
->orderBy('WorkOrder.create_date', 'desc')
->groupBy('Customer.customer_id');

Laravel query - getting objects and their counts from related table

I have table articles and it's related tables comments, views and likes which have a field article_id and in my function I am sending name of the related table, with $request['option'], comments for example, with ajax, to get the top 5 most commented articles. But in my function I am getting from the query result with article_ids and counts and then I am iterating through the results with foreach loop and getting article object with article_id that I am sending in the query. I would like to avoid doing that query for each of the results from the first query. What would be the way to do it more elegantly and without so many calls to DB?
This is my code:
public function mostArticle(Request $request) {
$from = $request['from'];
$to = $request['to'];
$result = DB::table($request['option'])
->select(DB::raw('article_id'), DB::raw('count(*) as count'))
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('article_id')
->orderBy('count', 'DESC')
->take(5)
->get();
foreach($result as $val){
$article = Article::where('id', $val->article_id)->first();
$mostSomethingArticle[$article->id] = [];
$mostSomethingArticle[$article->id]['title'] = $article->title;
$mostSomethingArticle[$article->id]['summary'] = $article->summary;
$mostSomethingArticle[$article->id]['count'] = $val->count;
}
return json_encode($mostSomethingArticle);
}
You can use relations or joins. But im not sure, if this code is correct:
$result = DB::table($request['option'])
->select('article.id', 'article.title', 'article.summary', DB::raw('count('.$request["option"].'.id) as count'))
->join('article', 'article.id', '=', $request['option']."article_id")
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('article_id')
->orderBy('count', 'DESC')
->take(5)
->get();
return $result;

Laravel Eloquent, return rows where both conditions are True

I have a table of Weeks that is joined to a property table, Weeks table looking like this:-
PropID, WeekDate, Available
1 , 2015-07-04, Yes
1 , 2015-07-11, Yes
1 , 2015-07-18, No
2 , 2015-07-04, Yes
2 , 2015-07-11, No
2 , 2015-07-18, No
I want to select properties where both the weeks of the 4th and 11th are available. In the example above, I want to return two rows with PropID 1 as both are available and no rows from PropID 2 as only one of the weeks are available.
I've tried various ways, but either get nothing or always return the 1st, 2nd and 4th rows.
I think this is close, but it's still missing something as it is looking for dates that are <= AND >=
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->where(function($sub)
{
$sub->where('WeekDate', '>=', '2015-07-04');
$sub->where('WeekDate', '<=', '2015-07-11');
});
$q->where('Available', '=', 'Yes');
})
->get();
Not sure this helps, but the Property table is simply
PropID, PropName
1 , Property 1
2 , Property 2
Just found that this SQL works.
SELECT PropID FROM tblweeks WHERE WeekDate IN ('2015-07-04', '2015-07-11') AND Available = 'yes' GROUP BY PropID HAVING COUNT(*) = 2
This will give your result as Property 1 only:
$weeks = Property::whereHas('Week', function ($q) {
$q->where(function ($sub) {
$sub->whereIn('WeekDate', array('2015-07-04', '2015-07-11'));
$sub->where('Available', '=', 'y');
});
$q->groupBy('property_id');
$q->having('count(*)', '=', '2');
})->get();
There are some changes i have did in your query :
Please check this solution
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->where('WeekDate', '=', '2015-07-04');
$q->orWhere('WeekDate', '=', '2015-07-11');
$q->where('Available', '=', 'Yes');
})
->get();
This should work and will return desire output
There are some changes, the query might be using group by query :
Please check this solution
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->where('WeekDate', '=', '2015-07-04');
$q->orWhere('WeekDate', '=', '2015-07-11');
$q->where('Available', '=', 'Yes');
$q->group('WeekDate');
})
->get();
This should work and will return desire output
You actually need two whereHas for this:
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->where('WeekDate', '>=', '2015-07-04');
$q->where('Available', '=', 'Yes');
})
->whereHas('Week', function($q) use ($arrive)
{
$q->where('WeekDate', '<=', '2015-07-11');
$q->where('Available', '=', 'Yes');
})
->get();
I believe you do not need the second nested query.
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->where('WeekDate', '>=', '2015-07-04');
$q->where('WeekDate', '<=', '2015-07-11');
$q->where('Available', '=', 'Yes');
})
->get();
Updated
Have you looked into whereBetween.
$query = Property::whereHas('Week', function($q) use ($arrive)
{
$q->whereBetween('WeekDate', '2015-07-04', '2015-07-11');
$q->where('Available', '=', 'Yes');
})
->get();

Categories