I'm trying to figure out how to use the orWhere stament in laravel. I'm building a small app, allowing (gaming) clans to challenge other clans, either challenging a clan directly or challenge a match placed by another clan.
A clan can create a match or when challenging another team, a match is automatically created with a boolean that the match is a challenge. A clan that challenges another clan is always the "home playing team".
I want to display all received challenges (clan challenges or match challenges and how much), for all matches and clans a user is in. So yes, both teams and matches can have multiple challenges.
With my following code, I'm trying to get all the received challenges from my database for the current user and the $team_id_arr contains an array with all the team ids of a user.
$receivedChallenges = DB::table('challenges')
->select(
'matches.id as id',
'matches.date as date',
'matches.time as time',
'challenges.id as challenge_id',
DB::raw('count(challenges.id) as challenge_amount')
)
->leftjoin('matches', 'matches.id', '=', 'challenges.match_id')
->leftjoin('team_user as ht', 'ht.team_id', '=', 'matches.home_id')
->leftjoin('team_user as at', 'at.team_id', '=', 'matches.away_id')
->where('matches.played', '=', false)
->where('matches.planned', '=', false)
->where(function($query) use ($team_id_arr) {
$query
->where('matches.challenge', '=', true)
->where('at.user_id', '=', auth()->user()->id)
->where('challenges.opponent_id', 'matches.away_id')
// Or where...
->orWhere('matches.challenge', '=', false)
->where('challenges.opponent_id', $team_id_arr);
})
->havingRaw('count(challenges.id) > ?', [0])
->groupBy('matches.id')
->get();
When a match is a challenge, the current user is in the "away playing team", thus being the opponent_id in the challenge table.
When a match is not a challenge, the current user is always the clan filling opponent_id in the challenges table.
I'm using the havingRaw to only display the matches that have a challenge and I want to sort everything based on the matches.id. Is my use of the orWhere correct, because currently the received challenges for my dummy clan aren't showing up on my page.
In SQL (mySQL for example),
A AND B AND C OR D AND E
would be interpreted as
(A AND B AND C) OR (D AND E).
But since Eloquent allows queries to be constructed with commands in any order, some practices from SQL have to be translated differently.
In the case of orWhere, I highly recommend isolating the two alternate clauses.
$receivedChallenges = DB::table('challenges')
->select(
'matches.id as id',
'matches.date as date',
'matches.time as time',
'challenges.id as challenge_id',
DB::raw('count(challenges.id) as challenge_amount')
)
->leftjoin('matches', 'matches.id', '=', 'challenges.match_id')
->leftjoin('team_user as ht', 'ht.team_id', '=', 'matches.home_id')
->leftjoin('team_user as at', 'at.team_id', '=', 'matches.away_id')
->where('matches.played', '=', false)
->where('matches.planned', '=', false)
->where(function($query) use ($team_id_arr) {
$query->where(function($query){
$query
->where('matches.challenge', '=', true)
->where('at.user_id', '=', auth()->user()->id)
->where('challenges.opponent_id', 'matches.away_id')
})->orWhere(function($query) use($team_id_arr){
$query
->where('matches.challenge', '=', false)
->where('challenges.opponent_id', $team_id_arr);
});
})
->havingRaw('count(challenges.id) > ?', [0])
->groupBy('matches.id')
->get();
Related
I have a complex query and it works, now i need to join users table and get 2 different value of it based on 2 different tables here is where things messed up.
Code
I have commented issue part as well as data that should be returned
$datas = DB::table('projects')
->orderBy('projects.id', 'desc')
->join('customers', 'projects.customer_id', '=', 'customers.id')
->leftjoin('project_schedules', 'projects.id', '=', 'project_schedules.project_id')
->leftjoin('project_schedule_details', 'project_schedules.id', '=', 'project_schedule_details.schedule_id')
->leftjoin('project_schedule_visits', 'projects.id', '=', 'project_schedule_visits.project_id')
// issue tables (project_admins) and (project_shoppers)
->leftjoin('project_admins', 'projects.id', '=', 'project_admins.project_id')
->leftjoin('project_shoppers', 'projects.id', '=', 'project_shoppers.project_id')
->groupBy('projects.id')
->select(
'projects.name as project',
'customers.companyName as customer',
'project_schedule_details.date as schedule_date',
'project_schedule_details.description as schedule_description',
'project_schedule_details.actual_cost as schedule_actual_cost',
'project_schedule_visits.from_date as visit_from_date',
'project_schedule_visits.to_date as visit_to_date',
'project_schedule_visits.description as visit_description'
// 'project_admins.user.username as admin' //i.e. user 1
// 'project_shoppers.user.username as shopper' // i.e user 2
)
->get();
Explanation:
I need to join users table to project_admins table as well as project_shoppers table and return related users to those tables.
Then I would have user 1 returned based on project_admins table
And user 2 based on project_shoppers table.
Any idea how to achieve that goal?
Under the leftJoins you can add the extra joins for getting the users:
->leftJoin('users','users2.id','=','project_admins.user_id')
->leftJoin('users AS users2','users2.id','=','project_shoppers.user_id')
In your select you can get the details like this:
->select(
...,
'users.username AS admin',
'users2.username AS shopper'
)
Hello i have this function
public function readData(){
$TableB1 = \DB::table('users')
->join('group_user', 'users.id', '=', 'group_user.user_id')
->join('groups', 'groups.id', '=', 'group_user.group_id')
->join('meetings', 'users.id', '=', 'meetings.owned_by_id')
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
)
->get();
foreach ($TableB1 as &$data){
$meetings = \DB::table('meetings')
->where('company_id', 1)->where('owned_by_id', $data->id)
->where(\DB::raw('MONTH(created_at)'), Carbon::today()->month);
echo $meetings->count();
}
return $TableB1;
}
i retrieve some data from database and return them and use AJAX Call to use them later
The problem is i have a table called users and table called meetings
i want to know how many meetings every user done everyday
so to do this i made a for each to take the user_id and use it to get the count
of meetings done by each user
for example in meetings table i have a owned_by_id field which have the user_id
so what the code does if it found for example if owned_by_id(6) repeated in
meetings table 4 times it will return 4
but this is what i get in the browser
instead what i want to get is something like this
im using Laravel 5.7 and sorry i know my question is unclear this is the 1st time i have ever asked question on stackoverflow
Image
If you want count of meetings then you may use laravel eloquent method with is: withCount();
Like this:
$users = User::with('meetings')->withCount('meetings')->get();
If you will do this then you will get meetings_count with your user object.
And if you have still any doubt you may refer following link:
https://laravel.com/docs/5.8/eloquent-relationships
Thnak you!
You could add a new column in the select() using the COUNT SQL statement:
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
\DB::raw('(
SELECT COUNT(meetings.id) FROM meetings GROUP BY meetings.owned_by_id
) as meetings')
)
I have a project which has management of my investments, that is, it takes my daily statement and saves it in my project so that I can see how much it is yielding, in summary I have a table that are these values daily, I can already generate the information separated by day and it works perfectly (in fact it is a little more complex than this what I do but the basis is this);
But now it's getting bad to see when I get a very large date range for example 1 year, it lists every day, I wanted a way to group by month or week,
Thanks in advance for any help.
$rows = AtivosExtrato::select('titulo_id', DB::raw('SUM(valor_bruto_atual) AS valor'), 'data_imports.data_import as created_at')
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('data_imports.data_import')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();
Briefly explaining what each eloquent information is:
AtivosExtrato: model where the daily income information is;
1) join: foreign table for the names of the titles
2) join: foreign table for the broker's name
3) join: table that saves the date of the import and relates to the id in the asset tableExtrato, it has a function to reduce the weight in the time of the searches and to gain performance.
where: limiting to the user in question
WhereBetween: limiting to date range
1) groupBy: Grouping by titles
2) groupBy: grouping by date of import
Table structure:
ativos_extrato
ativos_extratos foreign key
data_imports
Solution:
$rows = AtivosExtrato::select(
'titulo_id',
DB::raw('SUM(valor_bruto_atual) AS valor'),
'data_imports.data_import as created_at',
DB::raw('WEEK(data_imports.data_import) AS weeknumber')
)
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereIn('ativos_extratos.data_import_id',
DataImport::Select(DB::raw('max(ID)'))
->whereBetween('data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy(db::raw('Week(data_import)')) )
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('weeknumber')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();
Add DB::raw(WEEK(data_imports.data_import) AS weeknumber) and then replace ->groupBy('data_imports.data_import') with ->groupBy('weeknumber') and the same with MONTH() function if you want to group by month: add another select column DB::raw(MONTH(data_imports.data_import) AS monthnumber) and replace ->groupBy('data_imports.data_import') with ->groupBy('monthnumber'). So the whole Eloquent query with week grouping would be:
$rows = AtivosExtrato::select('titulo_id', DB::raw('SUM(valor_bruto_atual) AS valor'), 'data_imports.data_import as created_at', DB::raw('WEEK(data_imports.data_import) AS weeknumber'))
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('weeknumber')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();
Here's my situation I have joined tables but the problem is some of those columns have the same name from other tables. What I want to know is how I can prevent this from happening. The columns that have the same name are created_at but I only want to use methods' table created_at (methods.created_at). Here is my code to explain my situation better
$filtered_table = Method::leftJoin('users', 'users.id', '=', 'methods.created_by')
->leftJoin('roles', 'roles.id', '=', 'users.role_id')
->leftJoin('types', 'types.id', '=', 'methods.type_id')
->where($request->filters)//will act as a searchmap
->get([ 'users.username', 'users.id AS users_id', 'methods.*', 'methods.id AS method_id', 'methods.name AS method_name', 'roles.id AS role_id', 'roles.name AS role_name',
'types.id AS type_id_typetable', 'types.name AS type_name']);
notice how ->where is an array of objects, I am using it as a searchmap for the clause. But my problem is like what I said above that the tables has the same name on some columns like for example created_at, the other columns doesn't matter since I am not using it.
The question is how do I explicitly tell the query that I am using the methods.created_at when I am searching it through the searchmap (In this case, $request->filters['created_at']. Please, let me know if you need any more details.
EDIT
if($("#date_select_off").val() == "daily") {
let day = $("#day_date").val();
filter_list.created_at = day;
}
in this code in jquery I am naming the key the same as the column so that I can use it as parameter in the php query. But my like my initial problem I simply can't name it filter_list.methods.created_at any help with this is greatly appreciated.
EDIT 2
How would I use a 'LIKE' query to that particular key value pair?
->where($request->filters)//will act as a searchmap
->orWhere('methods.created_at', 'LIKE', $request->filters['methods.created_at'])
I tried doing this but it is just wrong since the key value pair is already hitting on the first where clause.
EDIT 3
It could use some improvements but yeah
$filtered_table = Method::leftJoin('users', 'users.id', '=', 'methods.created_by')
->leftJoin('roles', 'roles.id', '=', 'users.role_id')
->leftJoin('types', 'types.id', '=', 'methods.type_id')
->where($request->filters)//will act as a searchmap
->orWhere('methods.created_at', 'LIKE', '%' . $request->filters['methods.created_at'] . '%')
->get([ 'users.username', 'users.id AS users_id', 'methods.id AS method_id', 'methods.name AS method_name', 'methods.created_at AS method_created_at', 'roles.id AS role_id', 'roles.name AS role_name',
'types.id AS type_id_typetable', 'types.name AS type_name']);
Change your model class as per your requirements to specify what columns you want selected:
public function someModel() {
return $this->belongs_to('otherModel')->select(array('id', 'name'));
}
In this case pass the fully qualified column name in where clause like:
->where('methods.created_at', '=', $request->filters)
or create a table alias and use the alias like:
SELECT col from methods as t1,
...
WHERE t1.col = 'some value';
I've searched and tried a lot, but unfortunately, I didn't solve my problem. So, I'm posting my question here, please look and suggest me some solution.
I have few tables to manage users like users, profiles, groups, and group_user. Now, I want to retrieve all user name which are not the member of a particular group.
Efforts
$users = DB::table('users')
->join('profiles', 'users.id', '=', 'profiles.user_id')
->join('group_user AS gu', 'gu.user_id', '!=', 'users.id')
->join('groups', 'groups.id', '=', 'gu.group_id')
->where('groups.label', '=', $grouplabel)
->lists(DB::raw("CONCAT_WS(' ',profiles.firstname, profiles.lastname) AS name"),'users.id as id');
I'm executing the query above to get list of users which are not the member of a particular group, but I'm not able to solve it 'til now.
If I change != to = then I get the result of all users who are in the particular group.
Table record and structure in the image.
As, you can see I have 5 users, out of which 3 users having admin group and 2 are not. If I run the query for admin group, then there should be remaining 2 user or if I run query for test group then I should get 5 users.
you don't need to change the join part, all you need to change or add up in your where() section
$users = DB::table('users')
->join('profiles', 'users.id', '=', 'profiles.user_id')
->join('group_user AS gu', 'gu.user_id', '=', 'users.id') // mark it as '='
->join('groups', 'groups.id', '=', 'gu.group_id')
->where('groups.label', '<>', $grouplabel) // change here, see below description
->lists(DB::raw("CONCAT_WS(' ',profiles.firstname, profiles.lastname) AS name"),'users.id as id');
this will ignore the particular group (eg: profile) and will return all other users except this group (profile)
Edited
I just removed the profile section from query, to verify the relationships, once you get the results then we will add up profile section, just run this query
select * from users as u
inner join group_user as gu
on
gu.user_id = u.id
inner join groups as g
on
g.id = gu.group_id where
groups.label <> 'Tester'
Edited 2
$users = DB::table('users')
->join('profiles', 'users.id', '=', 'profiles.user_id')
->join('group_user AS gu', 'gu.user_id', '=', 'users.id')
->join('groups', 'groups.id', '=', 'gu.group_id');
//if users exists in specific group
if($users->where('groups.label', '=', $grouplabel)->count() > 0 ){
$result = $users->where('groups.label', '=', $grouplabel)
->lists(DB::raw("CONCAT_WS(' ',profiles.firstname, profiles.lastname) AS name"),'users.id as id');
} // return all users
else{
$result = $users->lists(DB::raw("CONCAT_WS(' ',profiles.firstname, profiles.lastname) AS name"),'users.id as id');
}