How to insert counts of rows by joining 3 tables on sql? - mysql

I am trying to join 3 tables and get counts of each contact's cases. So far I have this query written, but the result shows me contacts who has cases. I'd like to have a new column where it would show me "No of cases" for each contact, so the result should be 3 rows, 3 columns (last column is counts of cases)
Table A (Contacts)
+-----------------------+----+---------------------------------+
| Name | id | Organization |
+-----------------------+----+---------------------------------+
| Heidi Wilson-Reynolds | 2 | Alabama Arts Services |
+-----------------------+----+---------------------------------+
| Dr. Andrew Zope | 3 | Connecticut Empowerment Academy |
+-----------------------+----+---------------------------------+
| Rolando Cooper Sr. | 8 | Dutton Advocacy Trust |
+-----------------------+----+---------------------------------+
Table B (Case Contacts)
+----+---------+------------+
| id | case_id | contact_id |
+----+---------+------------+
| 1 | 1 | 2 |
+----+---------+------------+
| 2 | 2 | 3 |
+----+---------+------------+
| 3 | 3 | 8 |
+----+---------+------------+
| 4 | 4 | 2 |
+----+---------+------------+
| 5 | 5 | 3 |
+----+---------+------------+
| 6 | 6 | 8 |
+----+---------+------------+
Table C (Cases)
+----+-----------+
| id | status_id |
+----+-----------+
| 1 | 1 |
+----+-----------+
| 2 | 1 |
+----+-----------+
| 3 | 1 |
+----+-----------+
| 4 | 1 |
+----+-----------+
| 5 | 1 |
+----+-----------+
| 6 | 1 |
+----+-----------+
Query:
SELECT
A.display_name AS 'Name',
A.organization_name AS 'Organization'
FROM
A
INNER JOIN
B ON A.id = B.contact_id
INNER JOIN
C ON B.case_id = C.id
WHERE
A.contact_type = 'Individual' and C.status_id = 1; # Case status 1 is "Ongoing"
Result:
+-----------------------+---------------------------------+
| Name | Organization |
+-----------------------+---------------------------------+
| Heidi Wilson-Reynolds | Alabama Arts Services |
+-----------------------+---------------------------------+
| Dr. Andrew Zope | Connecticut Empowerment Academy |
+-----------------------+---------------------------------+
| Rolando Cooper Sr. | Dutton Advocacy Trust |
+-----------------------+---------------------------------+
| Heidi Wilson-Reynolds | Alabama Arts Services |
+-----------------------+---------------------------------+
| Dr. Andrew Zope | Connecticut Empowerment Academy |
+-----------------------+---------------------------------+
| Rolando Cooper Sr. | Dutton Advocacy Trust |
+-----------------------+---------------------------------+
This is the result I would like it to show, I think I need to use COUNT() function:
+-----------------------+---------------------------------+-----------------+
| Name | Organization | number_of_cases |
+-----------------------+---------------------------------+-----------------+
| Heidi Wilson-Reynolds | Alabama Arts Services | 2 |
+-----------------------+---------------------------------+-----------------+
| Dr. Andrew Zope | Connecticut Empowerment Academy | 2 |
+-----------------------+---------------------------------+-----------------+
| Rolando Cooper Sr. | Dutton Advocacy Trust | 2 |
+-----------------------+---------------------------------+-----------------+

Use group by
SELECT
A.display_name AS 'Name',
A.organization_name AS 'Organization',
count(*) AS 'number_of_cases'
FROM
A
INNER JOIN
B ON A.id = B.contact_id
INNER JOIN
C ON B.case_id = C.id
WHERE
A.contact_type = 'Individual' and C.status_id = 1; # Case status 1 is "Ongoing"
GROUP BY A.display_name, A.organization_name
The count(*) count the number of row that match the same value for the grouped by column .. in your case you have three distinct value for (name, Organization)
the the group by clause return this three different rows .. ad for each of this row count the number of rows that have the same value for name and Organization.
In you sample all the three value for (name, Organization) have 2 rows each ..
see this for brief tutorial for aggregation function
http://www.w3schools.com/sql/sql_functions.asp
http://www.sql-tutorial.com/sql-aggregate-functions-sql-tutorial/

Use GROUP BY NAME, ORGANIZATION and count the results using the output of this query. Basically you can include this output in another SELECT statement to get desired result

Related

MYSQL query with multiple reference tables

I have the following tables:
users
id | fname | lname
1 | Ron | Jones
2 | Jon | Don
3 | Sam | Bolt
niche
id | name
1 | Arts
2 | Sports
3 | Fashion
compensation
id | type
1 | Monetary Payments
2 | Free Products
3 | Experiences
Then I have two reference tables:
user_niche
id | userid | nicheid
1 | 1 | 2
2 | 1 | 3
3 | 2 | 1
4 | 2 | 3
5 | 3 | 1
6 | 3 | 2
And finally user_comp
id | userid | compid
1 | 1 | 1
2 | 1 | 2
3 | 2 | 3
4 | 3 | 1
5 | 3 | 2
6 | 3 | 3
What I want to achieve through query is as follows:
users.id | users.fname | users.lname | niches | compensations
1 | Ron | Jones | Sports, Fashion | Monetary Payments, Free Products
2 | Jon | Don | Arts, Fashion | Experiences
3 | Sam | Bolt | Arts, Sports | Monetary Payments, Free Products, Experiences
But my query (as follows) keeps repeating the niches and compensations in a way I cannot understand. Can someone please help me accomplish the required result?
SELECT users.id, users.fname, users.lname, GROUP_CONCAT(niche.name) AS niches, GROUP_CONCAT(compensation.type) AS compensations
FROM users
JOIN user_niche ON users.id = user_niche.userid
JOIN user_comp ON users.id = user_comp.userid
JOIN niche ON user_niche.nicheid = niche.id
JOIN compensation ON user_comp.compid = compensation.id
GROUP BY users.id
Help and suggestion is much appreciated.

mySQL SELECT query from multiple tables

I need a help with mySQL SELECT query from multiple tables. I have got four tables: school, discipline, pupils and teams.
School table looks like:
+------+---------+---------------+----------+
| id | name | discipline_id | pupil_id |
+------+---------+---------------+----------+
| 1 | one | 2 | 5 |
+------+---------+---------------+----------+
| 2 | two | 3 | 8 |
+------+---------+---------------+----------+
| 3 | three | 4 | 12 |
+------+---------+---------------+----------+
Discipline table looks like:
+------+---------+
| id | name |
+------+---------+
| 1 | math |
+------+---------+
| 2 | bio |
+------+---------+
| 3 | liter |
+------+---------+
| 4 | geo |
+------+---------+
Teams table looks like:
+------+---------+---------------+-----------+
| id | name | school_id | member_id |
+------+---------+---------------+-----------+
| 1 | T1 | 1 | 3 |
+------+---------+---------------+-----------+
| 2 | T2 | 3 | 3 |
+------+---------+---------------+-----------+
| 3 | T3 | 2 | 9 |
+------+---------+---------------+-----------+
The result of disciplines I need to get with a "SELECT from discipline..." query by "member_id = 3" is:
+-----------------+---------------+
| discipline_name | discipline_id |
+-----------------+---------------+
| bio | 2 |
+-----------------+---------------+
| geo | 4 |
+-----------------+---------------+
By matching member's school and then getting its discipline, if it makes sense...Is it possible to do with just one mySQL query?
Type of: member_id 3 => school_id 1,3 => discipline_id = show related disciplines names and ids which are 2, 4
Thank you very much...
Your goal is not clear or makes no sense to me.
But here is what you are literally asking for:
SELECT
s.discipline_id
d.name
FROM teams t
LEFT JOIN school s
ON s.id = t.school_id
LEFT JOIN discipline d
ON d.id = s.discipline_id
WHERE t.member_id = 3

MySQL Limit Results Based on Join Table

I have 2 tables,but linked in many to many relations so 3 tables :
Table Author :
idAuthor,
Name
+----------+-------+
| idAuthor | Name |
+----------+-------+
| 1 | Renee |
| 2 | John |
| 3 | Bob |
| 4 | Bryan |
+----------+-------+
Table Publication:
idPublication,
Title,
Type,
Date,
Journal,
Conference
+---------------+--------------+------+-------------+------------+-----------+
| idPublication | Title | Date | Type | Conference | Journal |
+---------------+--------------+------+-------------+------------+-----------+
| 1 | Flower thing | 2008 | book | NULL | NULL |
| 2 | Bees | 2009 | article | NULL | Le Monde |
| 3 | Wasps | 2010 | inproceding | KDD | NULL |
| 4 | Whales | 2010 | inproceding | DPC | NULL |
| 5 | Lyon | 2011 | article | NULL | Le Figaro |
| 6 | Plants | 2012 | book | NULL | NULL |
+---------------+--------------+------+-------------+------------+-----------+
Table author_has_publication :
Author_idAuthor,
Publication_idPublication
+-----------------+---------------------------+
| Author_idAuthor | Publication_idPublication |
+-----------------+---------------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 3 | 6 |
+-----------------+---------------------------+
What I want to do is get the top X author having the most publications.
I achieved to get the result avec the idAuthor having the most publications, using this request :
SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC;
I get the list of the authors id, ordered by the number of publications :
+-----------------+-------+
| Author_idAuthor | count |
+-----------------+-------+
| 3 | 3 |
| 2 | 2 |
| 1 | 2 |
| 4 | 1 |
+-----------------+-------+
but then when I try to select the author corresponding to the top X of the result set of the previous query I have an error
I am Trying this SELECT TOP 2 FROM author WHERE (SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC)=idAuthor;
I think it might be because my inside query return 2 rows, and I do a simple SELECT here or that I need a JOIN but i have no ideas how to use it here.
MySQL has no TOP keyword. It does however have a LIMIT keyword. Your query is invalid anyway.
There are a couple of options here. The following is an example of a correlated subquery: https://en.wikipedia.org/wiki/Correlated_subquery
SELECT
a.idAuthor,
a.Name ,
(SELECT COUNT(*) from author_has_publication ahp WHERE
ahp.Author_idAuthor = a.idAuthor) AS publication_count
FROM
author a
ORDER BY
publication_count DESC
LIMIT 2
As the referenced article notes, the above is inefficient as the subquery needs to be re-executed for each row of the result. If you do not actually need the count in the resultset then the below would be more efficient as the subquery is non-correlated and executed only once.
SELECT
a.idAuthor,
a.Name
FROM
author a
INNER JOIN
(select ahp.Author_idAuthor AS idAuthor, COUNT(*) as publication_count
FROM author_has_publication ahp GROUP BY ahp.Author_idAuthor LIMIT 2)
AS TEMP ON TEMP.idAuthor = a.idAuthor

Left join with count return one result

I have two tables.
|Table One: Adversitements-----------------------|
| ID | ADVTITLE |
|----|-------------------------------------------|
| 1 | IT Staff will be taken. |
| 2 | Human resources personnel will be taken. |
| 3 | CNC Operator will be taken. |
|Table Two: Applications-----|
| ID | ADVID | APPLICANTNAME |
|----|-------|---------------|
| 1 | 1 | John Doe |
| 2 | 1 | John Doe 2 |
| 3 | 1 | Jane Doe |
| 4 | 2 | John Doe |
| 5 | 2 | Jane Doe |
| 6 | 3 | John Doe |
I Want result:
| ADVTITLE | APPLICANTCOUNT |
|-------------------------------------------|----------------|
| IT Staff will be taken. | 3 |
| Human resources personnel will be taken. | 2 |
| CNC Operator will be taken. | 1 |
But returning a single result;
OUTPUT:
| ADVTITLE | APPLICANTCOUNT |
|-------------------------|----------------|
| IT Staff will be taken. | 6 |
MySQL Query;
SELECT adv.advtitle, COUNT(applications.id) as applicantCount
FROM advertisements as adv
LEFT JOIN applications
ON adv.id = applications.advid
All listings can be related to how the number of applicants?
SQL Fiddle Link: http://sqlfiddle.com/#!2/8644c/1/0
You missed the GROUP BY clause:
SELECT adv.advtitle, COUNT(applications.id) as applicantCount
FROM advertisements as adv
LEFT JOIN applications ON adv.id = applications.advid
GROUP BY adv.advtitle
ORDER BY applicantCount desc
Result:
ADVTITLE APPLICANTCOUNT
---------------------------------------------------------
IT Staff will be taken. 3
Human resources personnel will be taken.. 2
CNC Operator will be taken. 1
Fiddle Example
You need GROUP BY clause
SELECT adv.advtitle, COUNT(applications.id) as applicantCount
FROM advertisements as adv
LEFT JOIN applications
ON adv.id = applications.advid
GROUP BY applications.advid
SQL Fiddle
i already test it on my own try to paste it in your sqlfiddle :)
SELECT A.advtitle,COUNT(B.advid) AS ApplicantCount FROM advertisements A
LEFT JOIN applications B ON B.advid = A.id
GROUP BY A.id

Join only for specific rows where value matches a variable

I have multiple MySQL tables containing varying numbers of columns. After joining three of the tables, I have a resulting table that's structured as follows:
+------------+------------+-----------+-------+------+
| student_id | first_name | last_name | class | rank |
+------------+------------+-----------+-------+------+
| 1 | John | Doe | 2012 | 1 |
+------------+------------+-----------+-------+------+
| 2 | Suzy | Public | 2013 | 12 |
+------------+------------+-----------+-------+------+
| 3 | Mike | Smith | 2014 | 50 |
+------------+------------+-----------+-------+------+
I also have two additional tables that aren't involved in the initial join:
interest
+-------------+------------+-----------------------+----------------+
| interest_id | student_id | employer_interest | interest_level |
+-------------+------------+-----------------------+----------------+
| 1 | 1 | Wayne Enterprises | High |
+-------------+------------+-----------------------+----------------+
| 2 | 1 | Gotham National Bank | Medium |
+-------------+------------+-----------------------+----------------+
| 3 | 2 | Wayne Enterprises | Low |
+-------------+------------+-----------------------+----------------+
| 4 | 3 | Gotham National Bank | High |
+-------------+------------+-----------------------+----------------+
offers
+----------+------------+-----------------------+
| offer_id | student_id | employer_offer |
+----------+------------+-----------------------+
| 1 | 1 | Wayne Enterprises |
+----------+------------+-----------------------+
| 2 | 1 | Gotham National Bank |
+----------+------------+-----------------------+
| 3 | 2 | Wayne Enterprises |
+----------+------------+-----------------------+
The interest and offers table won't necessarily contain a record for every student_id but at the same time contain multiple records that reference a single student_id.
For each of the latter two tables, I'd like to:
Select all rows where the employer_interest or employer_offer value is equal to $var (a variable I've set in PHP)
Join these rows to the original table
For example, if $var is set to Wayne Enterprises, I'd like the resulting table to be:
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| student_id | first_name | last_name | class | rank | employer_interest | interest_level | employer_offer |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 1 | John | Doe | 2012 | 1 | Wayne Enterprises | High | Wayne Enterprises |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 2 | Suzy | Public | 2013 | 12 | Wayne Enterprises | Low | Wayne Enterprises |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 3 | Mike | Smith | 2014 | 50 | NULL | NULL | NULL |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
Is what I'm trying to do possible using just a MySQL query? If so, how do I do it?
it sounds like you just need a LEFT JOIN to the other tables since it appears you want to see all students from the first set regardless of any job offer/interest.
If so... ensure both the "Interest" and "Offers" tables have an index where the student ID is either a single element index, or first in that of a compound index.
select STRAIGHT_JOIN
ORS.Student_ID,
ORS.First_Name,
ORS.Last_Name,
ORS.Class,
ORS.Rank,
JI.Employer_Interest,
JI.Interest,
OFR.Employer_Offer
from
OriginalResultSet ORS
LEFT JOIN Interest JI
ON ORS.Student_ID = JI.Student_ID
AND JI.Employer_Interest = YourPHPVariable
LEFT JOIN Offers OFR
on JI.Student_ID = OFR.Student_ID
AND JI.Employer_Interest = OFR.Employer_Offer
To prevent "NULL" results in the employer interest, interest and offer, you can wrap them in a Coalesce() call such as (for all three columns on left join)
COALESCE( JI.Employer_Interest, " " ) Employer_Interest
Your query should be something like this:
select
s.student_id, s.first_name, s.last_name, s.class, s.rank,
i.employer_interest, i.interest_level,
o.employer_offer
from students s
left join interest i
on i.student_id = s.student_id
and i.employer_interest = 'Wayne Enterprises'
left join offers o
on o.student_id = s.student_id
and o.employer_offer = 'Wayne Enterprises'