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'
)
Related
I'm new to Laravel; I have been struggling with the following: I have four tables and would like to get all records from four tables but exclude rows with paid status in the transactions table.
Once the data has been selected from the tables using join, exclude all rows with paid status in the transactions table.
$invoiceData = DB::table('invoices')
->select('users.*', 'businesses.*', 'invoices.*', 'transactions.*')
->join('users', 'users.id', '=', 'invoices.user_id')
->join('businesses', 'businesses.id', '=', 'invoices.business_id')
->join('transactions', 'transactions.inv_id', '=', 'invoices.id')
->where('invoices.user_id', $id)
->where('transactions.status', '=', 'paid')
->get();
I considered an issue when viewing data called from database using two related tables users and roles which have this structure:
the users.role column contains an integer referring to the role record of roles table
the roles.name column contains the role name i.e. (user / admin / editor)
in my controller I used the laravel docs to build my query as I need to show a table in blade that holds users.name , users.email and roles.name that related to user by the schema:
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.name', 'users.email', 'roles.name')
->get();
actually it works and dumping data, but the issue is the confusion of the two name alike cols users.name and roles.name. it dumping only the roles.name value like this sample record:
{"name":"user","email":"user#asd.com"},{"name":"user","email":"new#asd.com"},{"name":"user","email":"jaeden93#example.org"}
even when I tried to select all cols of users table like below:
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.*', 'roles.name')
->get();
the users.name col still not showing!
Is there a way to solve this issue without changing table's column titles ?
You can give an alias to the column, to avoid problems with the same name
Use this
$users = DB::table('users')
->join('roles', 'users.role', '=', 'roles.id')
->select('users.*', \DB::raw('roles.name as role_name'))
->get();
It's the same to do this in SQL
SELECT users.*, roles.name as role_name FROM ...
Say I have 3 tables in my database.
'my_recipe', 'my_inventory' and 'ingredient'.
The 'my_recipe' table stores a list of raw_id's based on the 'ingredient' table and the 'quantity' need for the recipe. The 'my_inventory' table stores a list of raw_id's and 'have_quantity'.
So let's take a look at what I currently have at the moment. I have the following 2 queries:
First Query:
$recipe = DB::table('my_recipe as tA')
->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
->select('tA.user as user', 'tA.raw_id as raw_id', 'tA.quantity as quantity',
'tB.ingredient_name as ingredient_name')
->where('user', '=', $user)
->where('raw_id', '=', $raw_id)
->get();
Second Query:
$inventory = DB::table('my_inventory as tA')
->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
->select('tA.user as user', 'tA.have_quantity as have_quantity',
'tB.ingredient_name as ingredient_name')
->where('user', '=', $user)
->get();
The first query returns results that look something like this:
{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple"},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach"}
The second query returns results that look something like this:
{"user":"jack","have_quantity":30,"ingredient_name":"apple"},
{"user":"jack","have_quantity":20,"ingredient_name":"apple"},
{"user":"jack","have_quantity":10,"ingredient_name":"apple"},
{"user":"jack","have_quantity":1,"ingredient_name":"peach"},
{"user":"jack","have_quantity":1,"ingredient_name":"peach"}
Notice in the second query results I have to get the sum of the ingredients based on the 'ingredient_name' for my ideal output.
How can I get my ideal output in a single query?
My ideal output would look something like this:
{"user":"jack","raw_id":"853","quantity":2,"ingredient_name":"apple","have_quantity":60},
{"user":"jack","raw_id":"853","quantity":4,"ingredient_name":"peach","have_quantity":2}
It's basically the results of the first query with 'have_quantity' totals from the second query.
EDIT:
my_recipe Model:
'user', 'raw_id', 'quantity'
my_inventory Model:
'user', 'raw_id', 'have_quantity'
ingredient Model:
'raw_id', 'ingredient_name'
Note: In the ingredient model there can be rows with the same 'ingredient_name' but have different 'raw_id'.
Based on our chat conversation I managed to get some extra information on the table structure and what was needed to do to get the wanted results.
For those interested the information can be found here
Anyway I ended up creating the query like this:
SELECT
my_recipe.user AS user,
my_recipe.raw_id AS raw_id,
my_recipe.quantity AS quantity,
ingredient.ingredient_name AS ingredient_name,
IFNULL(SUM(my_inventory.have_quantity),0) AS have_quantity
FROM my_recipe
LEFT JOIN ingredient USING(raw_id)
LEFT JOIN ingredient AS ingredients USING(ingredient_name)
LEFT JOIN my_inventory ON my_inventory.raw_id = ingredients.raw_id
WHERE my_recipe.recipe_id = 853
AND my_recipe.user = 'jack'
AND my_inventory.user = 'jack'
GROUP BY ingredient_name;
Now converting into the needed structure:
$inventory = DB::table('my_recipe')
->leftJoin('ingredient', 'my_recipe.raw_id', '=', 'ingredient.raw_id')
->leftJoin('ingredient AS ingredients', 'ingredient.ingredient_name', '=', 'ingredients.ingredient_name')
->leftJoin('my_inventory', 'my_inventory.raw_id', '=', 'ingredients.raw_id')
->select(DB::raw('my_recipe.user AS user,my_recipe.raw_id AS raw_id,my_recipe.quantity AS quantity,ingredient.ingredient_name AS ingredient_name,IFNULL(SUM(my_inventory.have_quantity),0) AS have_quantity'))
->where('my_recipe.recipe_id', '=', $recipe_id)
->where('my_recipe.user', '=', $user)
->where('my_inventory.user', '=', $user)
->groupBy('ingredient_name')
->get();
Maybe this can solve you problem
//replace count by sum
$inventory = DB::table('my_inventory as tA')
->leftJoin('ingredient as tB', 'tA.raw_id', '=', 'tB.raw_id')
->leftJoin('my_recipe as tC', 'tC.raw_id', '=', 'tB.raw_id')
->select(DB::raw('tA.user as user, tB.ingredient_name as ingredient_name, SUM(tA.have_quantity) have_quantity'))
->where('user', '=', $user)
->groupBy('tB.ingredient_name, tA.user')
->get();
Let's try this:
$result = DB::table('ingredient as ing')
->rightJoin('my_recipe as rcp', 'ing.raw_id', '=', 'rcp.raw_id')
->rightJoin('my_inventory as inv', 'ing.raw_id', '=', 'inv.raw_id')
->select(DB::raw('
rcp.user as user,
ing.ingredient_name as ingredient_name,
rcp.have_quantity quantity,
SUM(inv.have_quantity) have_quantity
'))
->where('rcp.user', '=', $user)
->where('rcp.raw_id', '=', $raw_id)
->groupBy('rcp.user, ing.ingredient_name')
->get();
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');
}
Okay I have a some code written to retrieve data from some left join in my database, after retrieving this data I use the id from each to populate a modal. The thing is it works for some of the data that has been retrieve. For when i look at the query result I notice the id's are null for some valid data an some or not
$someuser = DB::table('users')
->join('sometable', 'sometable.user_id', '=','users.id')
->leftjoin('sometable', 'users.id', '=', 'skills.user_id')
->leftjoin('sometable', 'users.id', '=','schools.user_id')
->leftjoin('sometable', 'users.id', '=', 'languages.user_id')
->leftjoin('sometable','users.id', '=', 'memberships.user_id')
->leftjoin('sometable', 'users.id', '=', 'convictions.user_id')
->leftjoin('sometable', 'users.id', '=', 'work_experiences.user_id')
->select('users.*','sometable.name as sometablename','sometable.*')
->where('users.first_name', '<>', '')->whereNotNull('users.id')
->orderBy('sometable.updated_at', 'DESC')->groupby('users.first-name')->distinct()->paginate(100);
from that, the query result looks like:
{"total":966,"per_page":100,"current_page":1,"last_page":10,"from":1,"to":100,"data":[{"id":null, etc
What am simple saying why is my id null
I think its not showing me no ids over 1900 so if a user is over 1900 it showing me null
You are selecting * from multiple tables. Since you are also left joining, it's very likely there is nothing to join on so your database is returning those columns as null. Specifically select the id you need and alias it as something which will not be overwritten by another column.