Getting the count from another table based on a criteria - mysql

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.

Related

How count result from 3 tables

Please, take a look in these 3 tables:
Pets
+----+---------+-------+
| id | petname | owner |
+====+=========+=======+
| 1 | chew | 1 |
+----+---------+-------+
| 2 | yo | 2 |
+----+---------+-------+
| 3 | mah | 3 |
+----+---------+-------+
Owners
+----+-------+-----------+
| id | store | ownername |
+====+=======+===========+
| 1 | 1 | Jonh |
+----+-------+-----------+
| 2 | 2 | Joe |
+----+-------+-----------+
| 3 | 3 | Smith |
+----+-------+-----------+
Stores
+----+------------+
| id | storename |
+====+============+
| 1 | Lite Store |
+----+------------+
| 2 | Mega |
+----+------------+
| 3 | Corner |
+----+------------+
Is this possible to get this result?
+------------+------------+
| storename | Total Pets |
+============+============+
| Lite Store | 5 |
+------------+------------+
| Mega | 8 |
+------------+------------+
| Corner | 0 |
+------------+------------+
I tried for hours a lot of subqueries and joins, but I'm missing something, maybe Union?
With below I got close, but still far
SELECT storename, COUNT(distinct stores.storename) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT stores.storename, COUNT(distinct stores.storename) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT stores.storename, COUNT(distinct owners.id) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT COUNT(*),(SELECT COUNT(*) from stores) FROM pets
SELECT COUNT(*),(SELECT DISTINCT(COUNT(*)) from stores),(SELECT DISTINCT(COUNT(*)) FROM owners) FROM pets
SELECT DISTINCT(COUNT(*)), ( select count(DISTINCT(stores.storename)) from stores join owners on stores.id = stores.storename ) FROM pets
select stores.storename, (select count(*) from pets) from stores join owners on stores.id = stores.storename group by storename
select DISTINCT(stores.storename), (select count(*) from pets) from stores join owners on stores.id = stores.storename group by storename
select (count(stores.storename)), (select count(*) from pets) as total from stores join owners on stores.id = stores.storename group by storename
Is there any way to get the result above?
Any help will be great appreciated!
Thank you for providing your queries. I have formed a below query. Request you to try it and see if it works. if not, let me know
Select s.storename, count(p.petname) from pets p join owners o on p.owner=o.id join stores s on o.store=s.id group by 1

Get default value from JOIN query if join field value doesn't exist in another table

I have two tables customers and reviews. The structure is like this:
customers:-
|---------------------------------|
| id | name |
|---------------------------------|
| 1 | Thutmekri |
|---------------------------------|
| 3 | Conan |
|---------------------------------|
reviews:-
|-------------------------------------------|
| id | business_id | customer_id |
|-------------------------------------------|
| 1 | 1 | 1 |
|-------------------------------------------|
| 2 | 1 | 2 |
|-------------------------------------------|
| 3 | 1 | 3 |
|-------------------------------------------|
customer_id of reviews is id of customer.
The join query,
SELECT customers.name, reviews.id as review_id
FROM customers, reviews
WHERE customers.id = reviews.customer_id
returns the dataset like this:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
But I want it to return:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 2 | N/A |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
For customer_id in reviews, which doesn't have any data in customers table, I want 'N/A' to be displayed. How can I do it?
The following query also didn't help
SELECT reviews.id as review_id, COALESCE( name, 'N/A' )
FROM customers, reviews
WHERE customers.id = reviews.customer_id
Use a left join and switch the order of the tables in the join:
SELECT
r.id AS review_id,
COALESCE(c.name, 'N/A') AS name
FROM reviews r
LEFT JOIN customers c
ON c.id = r.customer_id;
SQLFiddle
Try this :
SELECT r.id as review_id, COALESCE( c.name, 'N/A' ) FROM reviews r
LEFT JOIN customers c ON c.id = r.customer_id
Use the Right outer join to achieve this:
SELECT
reviews.id as review_id,
COALESCE(name, 'N/A' )
FROM customers
RIGHT JOIN reviews
ON customers.id = reviews.customer_id;
You can use below query
SELECT
R.id AS review_id,
COALESCE(C.name, 'N/A') AS name FROM reviews R LEFT JOIN customers C ON R.customer_id = C.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

MySQL left join 2 tables order by count

I have 2 tables as below and want to have select both of them result by count(column) but doesn't work please advise.
review table
ID | RID | Name | comment
555|3000 | John | John comment
555|3001 | Ben | Ben comment
555|3002 | Smith| Smith comment
Likes table
U | PID
1 | 3000
2 | 3000
3 | 3000
4 | 3001
Expected result
ID | RID | Name | comment | votes
555|3000 | John | John comment | 3
555|3001 | Ben | Ben comment | 1
I'm expecting the result from select * from review with count PID column from Likes table
My current query is
SELECT * , (SELECT COUNT( PID ) FROM Likes AS votes WHERE there.ID = PID)
FROM review AS there
LEFT JOIN Likes b ON there.RID = b.PID
WHERE ID =555
AND there.RID = b.PID AND votes>0
ORDER BY votes DESC
But it did not woking, please advise.
Since you are after on reviews with votes only, you can make your query shorter(and perhaps faster) by converting LEFT JOIN to INNER JOIN, and eliminating detection of COUNT: http://www.sqlfiddle.com/#!2/1f920/3
SELECT r.ID, r.RID, r.Name, `Comment`, COUNT(RID) as votes
FROM review r
JOIN Likes l ON l.PID = r.RID
WHERE r.ID = 555
GROUP BY r.RID
ORDER BY votes DESC
Output:
| ID | RID | NAME | COMMENT | VOTES |
--------------------------------------------
| 555 | 3000 | John | John comment | 3 |
| 555 | 3001 | Ben | Ben comment | 1 |
SELECT ID, RID, Name, `Comment`, COUNT(RID) as votes
FROM review AS there
LEFT JOIN Likes b ON there.RID = b.PID
WHERE ID = 555
AND there.RID = b.PID
GROUP BY b.PID
HAVING votes > 0
ORDER BY votes DESC
sqlfiddle

Third join to get first_Name and Last_Name of account

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