Selecting all projects and tasks for a specific userID - mysql

I'm trying to select all Projects and Tasks from my database when given a specific userID.
The tables are as follows:
Users: UserID
Projects: ProjectID, UserID
Tasks: TaskID, ProjectID
I've tried things with nested queries, table joins and such but I'm no SQL expert by far and I'm struggling to get what I need. I can get all Tasks from a specific userID but that uses an Inner Join on the ProjectID which means that it doesn't return Projects that have 0 Tasks as Projects with no Tasks have nothing to be joined with.

You need to use LEFT JOIN to return the data:
select *
from users u
left join projects p
on u.userid = p.userid
left join tasks t
on p.projectid = t.projectid
where u.userid = ?
See SQL Fiddle with Demo
This will return all users regardless of whether they have records in the projects or tasks table.

Related

SQL statement from 2 tables

I am currently trying to run a sql statement to pull data from 2 tables I was wondering if someone could help me with my code. I would like to pull Project.Project_ID, Project.StartDate, Project.Users where Project_ID = 1 in both tables.
SELECT Project.Project_ID, Project.StartDate, Project.Users
FROM Project
INNER JOIN UserList ON Project.Project_ID=UserList.Project_ID
WHERE Project.Project_ID = '1';
I am not exactly sure what is your problem statement. If you can provide more details (DB Structure) that would be really helpful.
There could be more that one scenario you want to solve based on your data structure.
The only thing I see here is instead of Project.Users you should have UserList. Users. I assume User list tables having all the users details and it's not a pivot table. If it is then you need another join with User table.
SELECT
Project.Project_ID, Project.StartDate, UserList.Users
FROM
Project
INNER JOIN UserList ON Project.Project_ID=UserList.Project_ID
WHERE
Project.Project_ID = '1';
Please share your Database Structure.
With your model a user can only be linked to one project.
Below is with an joining table UserProject.
This way n users can take part to n projects. (n to n relation)
SELECT
p.id AS projectId,
p.startDate,
u.id AS userId,
u.name,
[...]
FROM
Project AS p,
UserProject AS up,
User AS u
WHERE
p.id = up.projectId
AND u.id = up.userId
AND p.id = 1;
And here is with a 1 to 1 relation
[...]
FROM
Project AS p,
User AS u
WHERE
p.id = u.projectId
AND p.id = 1;

fetch both created_by_id and assign_to_id names from two tables users and tasks

I have two Tables 1st
Users
SELECT users.*,tasks.*
from users
join tasks on users.id=tasks.assign_to
2nd is
Tasks
SELECT users.*,tasks.*
from users
join tasks on users.id=tasks.created_by
where tasks.created_by=5
here i want to show result this result is is not correct it shows only created_by correct but assign_to not correct.
I need Name of both created by and assign to users in one query
Try two joins of the users table.
SELECT
tasks.*,
created_by_user.name AS created_name,
assigned_to_user.name AS assigned_name
FROM tasks
INNER JOIN users created_by_user
ON created_by_user.id = tasks.created_by
INNER JOIN users assigned_to_user
ON assigned_to_user.id = tasks.assign_to
WHERE tasks.created_by = 5

MySQL query optimization: Multiple SELECT IN to LEFT JOIN

I usually go with the join approach but in this case I am a bit confused. I am not even sure that it is possible at all. I wonder if the following query can be converted to a left join query instead of the multiple select in used:
select
users.id, users.first_name, users.last_name, users.description, users.email
from users
where id in (
select assigned.id_user from assigned where id_project in (
select assigned.id_project from assigned where id_user = 1
)
)
or id in (
select projects.id_user from projects where projects.id in (
select assigned.id_project from assigned where id_user = 1
)
)
This query returns the correct result set. However, I guess the repetition of the query that selects assigned.id_project is a waste.
You could start with the project assignments of user 1 a1. Then find all assignments of other people to those projects a2, and the user in the project table p. The users you are looking for are then in either a2 or p. I added distinct to remove users who can be reached in both ways.
select distinct u.*
from assigned a1
left join
assigned a2
on a1.id_project = a2.id_project
left join
project p
on a1.id_project = p.id
join user u
on u.id = a2.id_user
or u.id = p.id_user
where a1.id_user = 1
Since both subqueries have a condition where assigned.id_user = 1, I start with that query. Let's call that assignment(s) the 'leading assignment'.
Then join the rest, using left joins for the 'optional' tables.
Use an inner join on user that matches either users of assignments linked to the leading assignment or users of projects linked to the leading project.
I use distinct, because I assumen you'd want each user once, event if they have an assignment and a project (or multiple projects).
select distinct
u.id, u.first_name, u.last_name, u.description, u.email
from
assigned a
left join assigned ap on ap.id_project = a.id_project
left join projects p on p.id = a.id_project
inner join users u on u.id = ap.id_user or u.id = p.id_user
where
a.id_user = 1
Here's an alternative way to get rid of the repetition:
SELECT
users.id,
users.first_name,
users.last_name,
users.description,
users.email
FROM users
WHERE id IN (
SELECT up.id_user
FROM (
SELECT id_user, id_project FROM assigned
UNION ALL
SELECT id_user, id FROM projects
) up
INNER JOIN assigned a
ON a.id_project = up.id_project
WHERE a.id_user = 1
)
;
That is, the assigned table's pairs of id_user, id_project are UNIONed with those of projects. The resulting set is then joined with the user_id = 1 projects to obtain the list of all users who share the projects with the ID 1 user. And now it only remains to retrieve the details for those users, which in this case is done in the same way as in your query, i.e. using an IN clause.
I'm sorry to say that I don't have MySQL to thoroughly test the performance of this query and so cannot be quite sure if it is in any way better or worse than your original query or than the one suggested both by #GolezTrol and by #Andomar. Generally I tend to agree with #GolezTrol's comment that a query with simple (semi- or whatever-) joins and repetitive parts might turn out more efficient than an equivalent sophisticated query that doesn't have repetitions. In the end, however, it is testing that must reveal the final answer for you.

Checking whole array over a multiple JOIN

To filter a table output of selected entries from a single table i would need something like a multiple JOIN request through several tables.
I want to filter a table of people by a special column in the table. Lets say this column is "tasks." Now tasks is also another table with the column "people" and the values between those two tables are connected with an existant "join" table in the database, which is matching several IDs of one table to each ID of the other table.
Now if this would be simple as that i could just filter with an INNER JOIN and a special condition. The problem is, that the entries of the table "tasks" are connected to another table over a "join" table in the database. To simplify things lets say it is "settings". So each "task" consists of several "settings" which are connected via a join table in their IDs.
So what is the input?
I got an array of IDs, which are representing the settings-ids i do not want to be shown.
What should be the output?
As already said i want a filtered output of "people" while the filter is "settings."
I want the sql request to return each entry of the table "people" with only joined tasks that are not joining any of the "setting-ids" from the array.
I hope you can help me with that.
Thanks in advance!
Example
Settings-Table:
1. Is in progress
2. Is important
3. Has unsolved issues
Tasks-Table: (settings.tasks is the join table between many tasks to many settings)
1. Task from 01.01.2012 - JOINS Settings in 1 and 3 (In progress + unsolved issues)
2. Task from 02.01.2012 - JOINS Settings in 2 (Is important)
3. Task from 03.01.2012 - JOINS Settings in 1 and 2 (...)
People-Table: (people.tasks is the join table between many people to many tasks)
1. Guy - JOINS Tasks in 1, 2, 3 (Has been assigned to all 3 tasks)
2. Dude - JOINS Tasks in 1 (Has been assigned to the Task from 01.01.2012)
3. Girl - JOINS Tasks in 2, 3 (...)
Now there is an array passed to a sql query
[2,3] should return noone because every person is assigned in a task that was either important or had unsolved issues!
[3] would return me only the person "Girl" because it is the only one that is assigned to tasks (2 and 3) that had no unsolved issues.
I hope it is clear now. :)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID = <Id you don't want>)
EDIT (for supplying multiple setting ids you don't want)
SELECT DISTINCT PEOPLE.*
FROM PEOPLE INNER JOIN PEOPLE_TASKS ON PEOPLE.PERSON_ID = PEOPLE_TASKS.PERSON_ID
WHERE TASK_ID NOT IN (SELECT DISTINCT TASK_ID
FROM TASK_SETTINGS
WHERE SETTING_ID IN (<Id you don't want>))
First you have to join table people and table tasks with the join table, let's call it people_tasks.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
Then you have to join table tasks and table settings with the join table, let's call it tasks_settings. You have to join them in the current select.
select distinct p.* from people p
inner join people_tasks pt on p.people_id = pt.people_id
inner join tasks on t.tasks_id = pt.tasks_id
inner join tasks_settings ts on t.tasks_id = ts.tasks_id
inner join settings s on s.settings_id = ts.settings_id
and now you have all people connected with its tasks and its settings. Finally you need the restriction. With the people with the settings selected, you choose the others like this:
select distinct p.people_id from people p
inner join people_tasks pt on p.people_id = pt.people_id
where p.people_id not in (
select distinct p2.people_id from people p2
inner join people_tasks pt2 on p2.people_id = pt2.people_id
inner join tasks t2 on t2.tasks_id = pt2.tasks_id
inner join tasks_settings ts2 on t2.tasks_id = ts2.tasks_id
inner join settings s2 on s2.settings_id = ts2.settings_id
where s2.settings_id in (list of ids)
)

Retrieve Clients from Projects User Belongs to

Users can have multiple projects and projects can have multiple clients.
How do I get all the unique clients from the projects a user belongs to?
Tables:
- Users
- Projects
- Clients
- Project Clients
SELECT client_id, client_name FROM clients.. ? JOINS, USING.. ?.. what?
Firstly, if users can have multiple projects, you'll need a Project-Users table.
Given that, you can get what you want using either of these pieces of SQL:
select distinct c.id from
clients c
join projectclients pc on c.id=pc.clientid
join projects p on pc.projectid=p.id
join projectusers pu on p.id=pu.projectid
join users u on u.id=pu.userid
where u.id=3
select distinct c.id from
clients c join projectclients pc on c.id=pc.clientid
where pc.projectid in
(select projectid from
users u join projectusers pu on u.id=pu.userid
where u.id=3)