How to Select data trough 2 tables with ONE Query - mysql

Every client has their own project but not all of them has project.
I want to select all clients that has project but I do not know how to do it!
I get all clients with this query:
SELECT `clients` FROM `reps` WHERE `clients` != ''
My goal is to get data which has only project
These are my database tables:
Table Clients: (Table name = reps)
1 id varchar(12) // example: stckvrflw
2 ctitle varchar(100) // example: StackOverflow
Table Projects: (Table name = verkocht)
1 id varchar(11) // example: 1
2 title varchar(100) // example: This is an Example
Do you have a solution on my problem?

You have the client in the milestones table, so doesn't this do what you want?
SELECT DISTINCT m.client
FROM `milestones` m;

You have to join the projects and the milestones tables. Since you gave no information on your database shema, the field names have to be adjusted. You also have to check for deleted or hidden flags if you have some:
SELECT c.* FROM clients c
INNER JOIN projects p ON p.client = c.id
INNER JOIN milestones m ON m.project = p.id
GROUP BY c.id

Related

MySql join tables with filter at one of table

noobs here.
i have 2 master tables its employees and trainings each of that table has primary key
and 1 table training_histories to mapping employee to training that have been taken. so my scheema looks like this.
table employees : id, employee_name, etc.
table trainings : id, training_name, etc.
table training_histories : id, employee_id, training_id
I want to do a query to find out which employees have been included in a particular training with the training_id parameter.
i try this query
SELECT *
FROM employees AS emp
LEFT OUTER JOIN employee_training_histories AS th ON emp.emp_id = th.emp_id
LEFT OUTER JOIN trainings AS trn ON th.training_id = trn.training_id
WHERE th.training_id = 1
but its not works like my expectations
i expect when training_id = 1 its showing like this
employee
training
a
javascript
b
javascript
c
null
d
null
when training_id = 2 its showing like this
employee
training
a
null
b
C++
c
C++
d
null
still showing all employee but training is depending on training_id
thanks for attention forgive me for my bad engglish..
You need to switch from LEFT JOIN to INNER JOIN.You can see the difference between the various joins here.
SELECT *
FROM employees AS emp
INNER JOIN employee_training_histories AS th ON emp.emp_id = th.emp_id
INNER JOIN trainings AS trn ON (th.training_id = trn.training_id AND th.training_id = 1)
P.S: You can directly place your filter in the ON clause for optimal results.

How to Join three tables properly

The main table has 4 columns:
User Activity Table
userActivityId userId therapistId activityId
1 1 1 1
Each of these columns is a table and these values are all foreign keys.
Basically im trying to run a query that will join to the users table and pull their first and last name based off the user Id.Same thing with therapist - join to the therapist table, pull first + last name.And finally Join to the Activity table and pull the activity name and path from the activity Id
The other tables look like this:
User Table
userId fName lName
Therapist Table
therapistId therapistFirstName therapistLastName
Activity Table
activityId activityTitle activityPath
So far my query looks like
SELECT
User_Activities.userId,
User_Activities.therapistId,
User_Activities.activityId,
Activities.activityTitle,
Activities.activityPath,
Users.fName,
users.lName,
Therapists.therapistFirstName,
Therapists.therapistLastName
FROM
User_Activities
INNER JOIN Users
ON User_Activities.userId = Users.userId
INNER JOIN Therapists ON
User_Activities.therapistId = Therapists.therapistId
INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
WHERE
User_Activities.userId = 1;
When I run this query It only returns 1 row as a result. However there are two activities in the User_Activites table assigned to userId 1.
If I change : INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
from an INNER JOIN to the LEFT JOIN it will display the second row, however the activityTitle and activityPath will be displayed as NULL in the second row.
userActivityId userId therapistId activityId activityId activityTitle activityPath fName lName therapistFirstName therapistLastName
1 1 1 1 1 Brain GZZ0zpUQ S C M D
11 1 1 1 NULL NULL NULL S C M D
You have pretty much answered your question. The second activity does not have a valid ActivityId.
If you want all activities for a user, then you should phrase the query as:
SELECT . . .
FROM Users u LEFT JOIN
User_Activities ua
ON ua.userId = u.userId LEFT JOIN
Therapists t
ON ua.therapistId = t.therapistId LEFT JOIN
Activities a
ON a.activityId = ua.userActivityId
WHERE u.userId = 1;
You want to start with the table where you want to keep all the rows. Then use LEFT JOIN to bring in other tables.
Two other changes of note:
Table aliases are used to simplify reading and writing the query. The SELECT needs to change to use the aliases.
The WHERE clause refers to the Users table rather than UserActivities.

Remove results from SELECT by conditions on multiple columns

So I have this feed of products
id man sup product
1 1 1 MacBook
2 1 2 iMac
3 2 1 Windows
4 2 2 Office
and then tables with manufacturers
id manufacturer
1 Apple
2 Microsoft
and suppliers
id supplier
1 TechData
2 Westcoast
Then, for some reasons, I don't want to show a manufacturer's products by a certain supplier, i.e.:
id man sup comment
1 2 1 TechData aren't allowed to sell Microsoft
2 1 2 hide all Apple products from Westcoast
Is there a way, in pure SQL, to show only the products which fall through my filter, in this case MacBook and Office? I believe this isn's just a WHERE NOT (x AND y) as the result will list the remaining combinations.
Thanks a lot!
This is just a variation on Return row only if value doesn't exist, except you're joining on two columns.
SELECT p.product, m.manufacturer, s.supplier
FROM products AS p
JOIN manufacturers AS m ON m.id = p.man
JOIN suppliers AS s ON s.id = p.sup
LEFT JOIN filter AS f ON p.man = f.man AND p.sup = f.sup
WHERE f.id IS NULL
DEMO
You can try this, mate:
First, create the temporary/real container for your custom manufacturer-supplier filter:
-- pivot temp/real table for suppliers - manufacturers
DROP TEMPORARY TABLE IF EXISTS `manufacturers_suppliers`;
CREATE TEMPORARY TABLE `manufacturers_suppliers` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`manufacturer_id` INT(11) UNSIGNED,
`supplier_id` INT(11) UNSIGNED,
PRIMARY KEY (`id`),
UNIQUE KEY (`manufacturer_id` ASC, `supplier_id` ASC)
);
-- populate pivot table
INSERT INTO `manufacturers_suppliers` (`manufacturer_id`, `supplier_id`)
VALUES
-- TechData aren't allowed to sell Microsoft
(2, 1),
-- hide all Apple products from Westcoast
(1, 2);
After that, using the content of the container, you only need to create a standard query for your result set.
-- create result
SELECT
p.id, p.product, # show product detail
s.id, s.supplier, # show supplier detail
m.id, m.manufacturer # show manufacturer detail
FROM
products p
INNER JOIN suppliers s ON s.id = p.sup
INNER JOIN manufacturers m ON m.id = p.man
LEFT JOIN `manufacturers_suppliers` ms ON
ms.manufacturer_id = man.id
AND ms.supplier_id = sup.id
WHERE ms.id IS NULL;
So that every time you have an update to your filter, you only update records not the actual query script. Cheers

SQL Genius need .. Complex MySQL query

I am trying to optimise my php by doing as much work on the MySQL server as possible. I have this sql query which is pulling data out of a leads table, but at the same time joining two tags tables to combine the result. I am looking to add a company which is linked through a relations table.
So the table that holds the relationship between the two is relations_value which simply states (I add example data)
parenttable (companies) | parentrecordid (10) | childtable (leads) | childrecordid (1)
the companies table has quite a few columns but the only two relevant are;
id (10) | companyname (my company name)
So this query currently grabs everything I need but I want to bring the companyname into the query:
SELECT leads.id,
GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status,
leads.probability
FROM `gs_db_1002`.leads
LEFT JOIN ( SELECT *
FROM tags_module
WHERE tagid IN ( SELECT id
FROM tags
WHERE moduleid = 'leads' ) ) as b
ON leads.id = b.recordid
LEFT JOIN `gs_db_1002`.tags as c
ON b.tagid = c.id
GROUP BY leads.id,
leads.status,
leads.probability
I need to be able to go into the relations_values table and pull parenttable and parentrecordid by selecting childtable = leads and childrecordid = 1 and somehow join these so that I am able to get companyname as a column in the above query...
Is this possible?
I have created a sqlfiddle: sqlfiddle.com/#!2/023fa/2 So I am looking to add companies.companyname as column to the query.
I don't know what your primary keys and foreign keys are that link each table together.. if you could give a better understanding of what ID's are linked to eachother it would make this a lot easier... however i did something that does return the correct result... but since all of the ID's are = 1 then it could be incorrect.
SELECT
leads.id, GROUP_CONCAT(c.tag ORDER BY c.tag) AS tags,
leads.status, leads.probability, companyname
FROM leads
LEFT JOIN (
SELECT * FROM tags_module WHERE tagid IN (
SELECT id FROM tags WHERE moduleid = 'leads' )
) as b ON leads.id = b.recordid
LEFT JOIN tags as c ON b.tagid = c.id
LEFT JOIN relations_values rv on rv.id = b.recordid
LEFT JOIN companies c1 on c1.createdby = rv.parentrecordid
GROUP BY leads.id,leads.status, leads.probability

sql - join 2 tables 10 times

I have 2 tables structured like this:
People
----------
>ID, Name, Surname
Projects
----------
>ID, Assistant#1, Assistant#2, Assistant#3, Assistant#4,
> Assistant#5, Assistant#6, Assistant#7, Assistant#8, Assistant#9,
> Assistant#10, lot of other columns..... (every assistant column
> contains an integer, the people ID)
Now, I want to query my DB and get a single row from Project table (let's suppose row with ID=3) containing all columns of project table and in particular have each assistant replaced with it's correct name and surname.
I've managed to do this (with a lot of joins), but with my little sql experience my code looks very bulky and i'm sure that there's a better way to do this.
Thanks in advance.
SELECT p.Name, p.Surname
FROM People p
CROSS JOIN Project j ON (p.PeopleID = j.Assistant1 OR
p.PeopleID = j.Assistant2 OR
p.PeopleID = j.Assistant3 OR
.. etc)
AND j.ProjectID = 3
Your performance will be awful, but that's the price you pay for having a horribly designed database. The better solution is to map a project and people by the means of a decomposition:
CREATE TABLE proj_people
People_ID INT
Project_ID INT
Your structure is not clear to me. I advice you to create a clutch for projects.
Tables:
Peoples
people_id, people_name, people_surname
Projects
project_id, project_name
Clutch
project_id, people_id
Because you set a number of (possible) assistants at 10, that dictates that you are going to have to write code to accomodate those 10 assistants. This can be done a few ways: (have not tested)
select * from projects proj
left join people p1 on proj.assistant1 = p1.peopleid
left join people p2 on proj.assistant2 = p2.peopleid
left join people p3 on proj.assistant3 = p3.peopleid
left join people p4 on proj.assistant4 = p4.peopleid
left join people p5 on proj.assistant5 = p5.peopleid
left join people p6 on proj.assistant6 = p6.peopleid
left join people p7 on proj.assistant7 = p7.peopleid
left join people p8 on proj.assistant8 = p8.peopleid
left join people p9 on proj.assistant9 = p9.peopleid
left join people p10 on proj.assistant10 = p10.peopleid
otherwise you could do some trickery with
select proj.projectID,
(select * from people where peopleID = proj.assistant1),
(select * from people where peopleID = proj.assistant2),
(select * from people where peopleID = proj.assistant3),
(select * from people where peopleID = proj.assistant4),
(select * from people where peopleID = proj.assistant5),
(select * from people where peopleID = proj.assistant6),
(select * from people where peopleID = proj.assistant7),
(select * from people where peopleID = proj.assistant8),
(select * from people where peopleID = proj.assistant9),
(select * from people where peopleID = proj.assistant10)
from projects proj
If possible, it might be best to re-structure your datatables, and have a single assistant mapped to a single projectID:
PeopleID, Name, Surname
ProjectID, PeopleID
Therefore, you could do just one inner join and you will return a row for each assistant:
select * from projects proj
inner join people p
on p.peopleID = proj.peopleid
where proj.projectID = PROJECTID
Your problem is that you are trying to solve a data presentation issue at the database level and this is rarely a good idea. You should have a table holding projectid and assistantid only, having the combination of both columns as the primary key of the table. This will allow you to join this table to the assistant table and the project table only once and get all the results you need. This will also have the benefit of allowing you to support many more assistants on a project in the future without having to alter your queries to add yet more joins.
In conclusion you should have 3 tables:
Project
Assistant
ProjectAssistant (projectid,assistantid)
you want to restructure your tables. I hate seeing tables with multiple columns for essentially the same thing multiple times. If you restructure to have 3 tables:
Person
PeopleID | Name | Surname
Project
ProjectID | ...other columns except Assistant
Project_Person
ProjectID | PersonID
That way you can assign multiple assistants to the same project without the need for multiple Assistant columns. Then you could use something like this to get the required results:
SELECT proj.ProjectID, pers.Name, pers.Surname
FROM Person pers
INNER JOIN Project_Person pp ON pp.PersonID = pers.PersonID
INNER JOIN Project proj ON proj.ProjectID = pp.ProjectID
This will not return a single row, but that is not how SQL is designed to work.
If you don't want to/can't change the table structure then maybe use a user defined function?
CREATE FUNCTION GET_ASS_NAME (n1 ASS_NO)
RETURNS VARCHAR(50)
DETERMINISTIC
BEGIN
DECLARE fullname VARCHAR(50);
SELECT fullname = CONCAT(NAME, ' ', SURNAME) FROM PEOPLE WHERE ID = n1;
RETURN fullname;
END|
then
select GET_ASS_NAME(1), GET_ASS_NAME(2), GET_ASS_NAME(3), ...
from PROJECTS
where ID = 3
Perhaps a cleaner design is:
People table:
People ID, Name, Surname
ProjectAssistants table:
Project ID, Assistant Person ID
Projects table:
Project ID, lots of other columns (but no Assistant columns)
Then, the SQL becomes something like:
SELECT pr.*, p.*
FROM Projects pr
JOIN ProjectAssistants p_a ON pr.ProjectID = p_a ProjectID
JOIN People p ON p_a.AssistantPersonID = p.PeopleID
WHERE ProjectID = X
Not tested :)
Select * from project pr
left join people pe1 on pe1.peopleid = pr.astint1
left join people pe2 on pe2.peopleid = pr.astint2
left join people pe3 on pe3.peopleid = pr.astint3
left join people pe4 on pe4.peopleid = pr.astint4
left join people pe5 on pe5.peopleid = pr.astint5
left join people pe6 on pe6.peopleid = pr.astint6
left join people pe7 on pe7.peopleid = pr.astint7
left join people pe8 on pe8.peopleid = pr.astint8
left join people pe9 on pe9.peopleid = pr.astint9
left join people pe10 on pe10.peopleid = pr.astint10
where pr.projectid = 3