Third join to get first_Name and Last_Name of account - mysql

I have the following query which matches Account_ID's on Accounts table with the AccountID's on project assigned table and displays the accounts assigned to a project:
SELECT proj.ProjectID, A.Project_Title, B.Account_ID, B.Username, B.Access_Type
FROM Project_Assigned proj
INNER JOIN Account B
ON proj.AccountID = B.Account_ID
INNER JOIN Project A
ON proj.ProjectID = A.Project_ID
WHERE proj.ProjectID = 1;
What I want to do now is get the First_Name, Last_Name from Client table and Agency_Employee table and display the information matched against the Account_ID's. Both Client_ID and Employee_ID are foreign keys of Account_ID. How would I add this information into the join above?
I have attempted to add an additional join but I always get a result set match 0 which I know shouldn't be the case.
Client Table:
+-----------+------------+-----------+
| Client_ID | First_Name | Last_Name |
+-----------+------------+-----------+
| 4 | Phil | Jones |
+-----------+------------+-----------+
Employee Table:
+-------------+------------+-----------+
| Employee_ID | First_Name | Last_Name |
+-------------+------------+-----------+
| 2 | John | Smith |
| 5 | Bob | Jones |
| 6 | Fred | Tucker |
+-------------+------------+-----------+
Account Table:
+------------+----------+
| Account_ID | Username |
+------------+----------+
| 1 | Dan |
| 2 | rjm |
| 3 | pw |
| 4 | Philly |
| 5 | bob |
| 6 | fred |
+------------+----------+
Project Assigned Table:
+-----------+-----------+
| ProjectID | AccountID |
+-----------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 4 |
+-----------+-----------+

I'm not sure, but you seem to indicate that for an Account with ID 5, the Client will have ID 5 and the Employee will have ID 5? Slightly odd, and you probably want to read up on normalisation, but shouldn't this work?
SELECT
proj.ProjectID,
Project.Project_Title,
Account.Account_ID, Account.Username,
Client.First_Name AS Client_First_Name, Client.Last_Name AS Client_Last_Name,
Employee.First_Name AS Employee_First_Name, Employee.Last_Name AS Employee_Last_Name
FROM `Project_Assigned` proj
INNER JOIN `Account` ON (proj.AccountID = Account.Account_ID)
INNER JOIN `Project` ON (proj.ProjectID = Project.Project_ID)
LEFT JOIN `Client` ON (Account.Account_ID = Client.Client_ID)
LEFT JOIN `Employee` ON (Account.Account_ID = Employee.Employee_ID)
WHERE proj.ProjectID = 1;
edit
Okay, I've updated my answer.
You'll have two first names and two lastnames, one of each will always be null.
If you only want one contact name, try this:
SELECT
COALESCE(Client.First_Name, Employee.First_Name) FirstName,
COALESCE(Client.Last_Name, Employee.Last_Name) LastName

SELECT c.First_Name, c.Last_Name, e.First_Name, e.Last_Name
FROM client c, employee e, account a
WHERE c.Client_ID = a.Account_ID OR e.Employee_ID = a.Account_ID
OR
SELECT c.First_Name, c.Last_Name
FROM client c, account a
WHERE c.Client_ID = a.Account_ID
UNION
SELECT e.First_Name, e.Last_Name
FROM employee e, account a
WHERE e.Employee_ID = a.Account_ID

Related

Find oldest account per company in sql

I have a few tables that look like the below
Users
-----------------------------------------
| id | policyId | createdAt | updatedAt |
-----------------------------------------
| 1 | 1 | 2017/8/5 | 2017/8/5 |
| 2 | 1 | 2016/4/5 | 2017/8/5 |
| 3 | 2 | 2017/7/2 | 2017/8/5 |
| 4 | 2 | 2018/8/5 | 2017/8/5 |
-----------------------------------------
Policies
------------------------------------------
| id | companyId | createdAt | updatedAt |
------------------------------------------
| 1 | 1 | 2017/8/5 | 2017/8/5 |
| 2 | 2 | 2016/4/5 | 2017/8/5 |
------------------------------------------
Companies
-----------------------------------------
| id | policyId | createdAt | updatedAt |
-----------------------------------------
| 1 | 2 | 2017/8/5 | 2017/8/5 |
| 2 | 1 | 2016/4/5 | 2017/8/5 |
-----------------------------------------
I need to answer the question "What is the id of the user for each company with the oldest account. So the output should look something like this.
Output
----------------------------------
| CompanyId | UserId | CreatedAt |
----------------------------------
| 1 | 2 | 2016/4/5 |
| 2 | 3 | 2017/7/2 |
----------------------------------
What I have gotten so far looks something like this but I know it is no were near correct.
SELECT c.id, MIN(u.createdAt) FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id;
This seems to let me get the oldest date for each company user but I am not sure how to correlate the users back to that date to get the user id's. I am thinking the query above might have to be a sub-query but that is about as far as my sql knowledge goes.
Any help would be appreciated.
I need to join the whole query to itself and join by comapny id and createdAt column.
see demo here: http://sqlfiddle.com/#!9/6f4ea7/22
SELECT c.id as companyID,
u.id as userID,
u.createdAt
FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
JOIN (SELECT c.id as companyID,
min(u.createdAt) as min_dt
FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id) sub
on c.id=sub.companyID
where u.createdAt=sub.min_dt
SELECT p.company_id, u.user_id, MIN(u.createdAt) FROM policies p, user_u,
(SELECT min(createdAt) as minDate, policy_id as policyId from users
GROUP BY policy_id) as sub
WHERE p.id = u.policy_id
AND sub.minDate = u.createdAt
AND sub.policy_id = u.policyId;
It will give u the expected output But some hard coded way
SELECT c.id as companyid,u.id as userid, MIN(u.createdAt) as createdAt FROM company as c
JOIN policies as p on p.cmpid = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id,u.id order by MIN(u.createdAt) asc limit 2;

MySQL query to print data from two tables

I need help with writing a MySQL query to print the respective department names and number of Employee for all departments in the Department table.
Expected output:
Executive 2
Technical 2
Production 1
A join command would be what you are looking for.
select transaction.username, transaction.transactiondate, products.price, products.quantity, products.description
from transaction, products
where products.productid = transaction.productid
and products.productid = IDHERE
I assume you have a simple table which structure as below show:
+--------+------+
| name | dep |
+--------+------+
| frank | IT |
| jack | IT |
| Sissel | FA |
| Li | FA |
| Mok | PM |
+--------+------+
You have three department maybe more, you can simple use count to fetch number of employee for all departments. and if you use group by dep you will get each number by you expect .
SELECT dep, count(*) FROM user_table GROUP BY dep;
And then you got:
+------+----------+
| dep | count(*) |
+------+----------+
| FA | 2 |
| IT | 2 |
| PM | 1 |
+------+----------+
Hope, that's all your need~
SELECT a.name as department_name, count(b.id) as num_of_employees
FROM department a INNER JOIN employee b ON a.dept_id = b.dept_id
GROUP BY a.dept_id

SQL Join tables and concat names from table 2

In Mysql 5.5 I´ve three tables like:
employee
ID | firstname | lastname
-------------------------
1 | John | Doe
2 | Henry | Fonda
employee_projects
ID | employee_id | project_id
------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
projects
ID | name
----------------------
1 | house
2 | cottage
3 | castle
How do I JOIN employee over emloyee_project with projects that I get as result:
ID | firstname | lastname | projects
-------------------------------------
1 | John | Doe | house, cottage
2 | Henry | Fonda | castle
You can join the tables together and use group_concat to aggregate the rows into csv values.
select e.*, t.projects
from employee e
left join (
select ep.employee_id, group_concat(p.name) as projects
from employee_projects ep
join projects p on ep.project_id = p.id
group by ep.employee_id
) t on e.id = t.employee_id;
You can use MySQL's group_concat:
select e.id
, e.firstname
, e.lastname
, group_concat(p.name) as projects
from employee e
left join
employee_projects ep
on e.id = ep.employee_id
left join
projects p
on ep.project_id = p.id
group by
e.id
, e.firstname
, e.lastname

Getting the count from another table based on a criteria

I have three tables and I would like to make a query of getting all companies. BUT I would like to know the amount of active employees by getting the last record per person from the people_history table and matching it with the company they work for.
Table: people
—————————————————————————————————————————————————
id | name | ssn | phone |
—————————————————————————————————————————————————
1 | John | 9591 | 12341234 |
2 | Jane | 1049 | 12340987 |
—————————————————————————————————————————————————
Table: people_history
—————————————————————————————————————————————————
id | person_id | company_id | time |
—————————————————————————————————————————————————
1 | 1 | 5 | stamp |
2 | 1 | 7 | stamp |
3 | 2 | 2 | stamp |
4 | 1 | 2 | stamp |
—————————————————————————————————————————————————
Table: companies
————————————————
id | name |
————————————————
1 | Name 1 |
2 | Name 2 |
… |
————————————————
By doing the following I don’t look for the last record per person.
SELECT c.name AS company_name, COUNT(h.id) AS employees
FROM companies c
LEFT JOIN people_history h ON h.id = c.company_id
GROUP BY c.id
Any suggestions?
Thank you!
Not tested but shut work:
SELECT c.name AS company_name, COUNT(h.id) AS employees
FROM companies c
LEFT JOIN (SELECT *
FROM people_history ph1
WHERE id = (SELECT MAX(id)
FROM people_history ph2
WHERE ph1.person_id = ph2.person_id)
) h ON h.id = c.company_id
GROUP BY c.id
This is easily solved with an anti-join:
SELECT c.name AS company_name, COUNT(h1.id) AS employees
FROM companies c
LEFT JOIN people_history h1 ON h1.id = c.company_id
LEFT JOIN people_history h2 ON h2.id = c.company_id AND h2.person_id = h1.person_id AND h2.id > h1.id
WHERE h2.id IS NULL
GROUP BY c.id
This counts only the last record (highest id) for each person in the person_history table.

MySQL multiple joins with Many-To-Many relations

I have three tables that matter to me: customer, client_assignment and customer_products. The last two are assignment tables for Many-To-Many-relations.
In client_assignment a customer of the type client gets associated with another customer (where customer_id is the parent and client_id the child).
In customer_product I associate customers with products.
A client can not be associated with a product, he inherits it from his parent-customer. In the example below this means, that Foo-1 also has product 3, because his father (Foo) has it.
customer (Customers):
+-------------+-------+----------+
| customer_id | name | type |
+-------------+-------+----------+
| 1 | Foo | customer |
| 2 | Foo-1 | client |
| 3 | Foo-2 | client |
| 4 | Bar | customer |
| 5 | Foob | customer |
+-------------+-------+----------+
client_assignment (Customer/Client-Assignment):
+-------------+-----------+
| customer_id | client_id |
+-------------+-----------+
| 1 | 2 |
| 1 | 3 |
+-------------+-----------+
customer_product (Customer/Product-Assignment):
+-------------+------------+
| customer_id | product_id |
+-------------+------------+
| 1 | 3 |
| 1 | 4 |
| 1 | 5 |
| 4 | 3 |
| 5 | 7 |
+-------------+------------+
I want to accomplish the following: Select all customers and their respective clients that are associated with product X.
My desired result for product 3 is something like this:
+-------------+-------+--------+
| customer_id | name | parent |
+-------------+-------+--------+
| 1 | Foo | null |
| 2 | Foo-1 | 1 |
| 3 | Foo-2 | 1 |
| 4 | Bar | null |
+-------------+-------+--------+
I've been thinking about this for a bit and it seems fairly complicated. I've tried joining them like the following:
SELECT c2.customer_id, c2.name, c1.customer_id as parent
FROM customer_product p, customer c1, customer c2, client_assignment a
WHERE
c1.customer_id = p.customer_id
AND c2.customer_id = a.client_id
AND a.customer_id = c1.customer_id
AND p.product_id = 3
I know, that this query will not give me the exactly desired result, but I've created it to start with. The main problem about it is, that it does only select the clients, and not the customers themselves. Therefore I only get Foo-1 and Foo-2 as a result, but not Bar or Foo.
The question is: Is this reasonably easily achievable, and how?
You can write another SELECT that gets the customers themselves, and combine the two with UNION:
SELECT c.customer_id, c.name, NULL AS parent
FROM customer AS c
JOIN customer_product AS p ON c.customer_id = p.customer_id
WHERE c.type = 'customer'
AND p.product_id = 3
UNION
SELECT c2.customer_id, c2.name, c1.customer_id AS parent
FROM customer_product AS p
JOIN customer AS c1 ON c1.customer_id = p.customer_id
JOIN client_assignment AS a ON a.customer_id = c1.customer_id
JOIN customer AS c2 ON c2.customer_id = a.client_id
WHERE c2.type = 'client'
AND p.product_id = 3
Because you have to get names of both clients and parents of the client, a way of doing it is by using UNION.
with customer_names as (select customer_id from s_customer_product where product_id =3),
client_names as (select client_id , customer_id as Parent_id from s_client_assignment join customer_names using(customer_id))
select customer_id , name , null as Parent from s_customers join customer_names using(customer_id)
union
select a.client_id , b.name , a.parent_id as Parent from client_names a, s_customers b where b.customer_id = a.client_id;