mysql count related table - mysql

Hi everyone I would like to count some entries, but I don't know if is possible to do it with joins. The situation is
I've got a tables
student_profile
Id | Name
---------
1 | Name1
2 | Name2
3 | Name3
student_application where profile_id is related to student_profile.id
Id | profile_id | Data
----------------------
1 2 data1
2 2 data2
3 2 data3
And table student_holiday
Id | app_id | date
-----------------------
1 2 2014-01-01
2 3 2014-02-02
So I'm getting all my student_application's with
Select sa.id, s.name From student_application sa
INNER JOIN student_profile s ON s.id = sa.profile_id
I would like to count how many holidays has a student, but I don't have profile_id in student_holiday table. There I've got app_id, so I can't do Left join student_holiday sh ON sh.app_id = sa.id, this wouldn't give the right number.
here sqlfiddle
Thanks in advance for any help.

SELECT student_profile.ID, student_profile.Name, student_holiday.ID
FROM (student_profile INNER JOIN student_holiday ON student_profile.ID = student_holiday.ID) INNER JOIN student_application ON student_holiday.ID = student_application.ID;
Here you go!!! Match ID in all the table as instructed above which is the key to get holidays.
OR match with profile_id
**SELECT student_profile.ID, student_profile.Name, student_holiday.ID
FROM (student_profile INNER JOIN student_holiday ON student_profile.ID = student_holiday.ID) INNER JOIN student_application ON Trim(student_holiday.ID) =
student_application.profile_id;**

Here is your data with the 3rd table joined:
Select s.name, sa.some_data as application_data,h.some_data as holiday_data
From student_application sa
INNER JOIN student_profile s ON s.id = sa.profile_id
INNER JOIN student_holiday h ON h.app_id = sa.id;
Note this will only return records that have an application with a holiday associated.
Then to count them, we just:
Select s.name, sa.some_data as application_data,count(h.some_data) as holiday_data
From student_application sa
INNER JOIN student_profile s ON s.id = sa.profile_id
INNER JOIN student_holiday h ON h.app_id = sa.id
GROUP BY s.name
Note this answer is based on the fieldnames you used in your sqlfiddle (Data = some_data and date = some_data)

Related

view specific queried value of each cell of table using some query in mysql?

I have one table containing some relation between tables?
school_id of school_table
class_id of class_table
teacher_id of teacher_table
subject_id of subject_table
Table sample:
I want to retrieve this whole table with replacing the name of each id from the child tables.
Ex. At time of retrieving the table as table or view i want to see each school name in place of school_id, class name in place of class_id and for other both class and subject with all rows in the table(above shown in image.)
Above shown image is my original table stored in mysql database. and i want this as result:
assign_subject_id | Schoolname | teachername | classname | subjectName | session
1 | UCDC | rahul | one | math | 2018-19
2 | UCDC | gopi | two | CS | 2018-19
school_table:
school_id | schoolname
7 | UCDC
and so forth for all table.
Thank you.
assuming you have school_table, teacher_table, class_table, subject_table
each with same pattern as school_table (school_id | schoolname)
the you need some join
INNER JOIN if all the relation key must match
select a.assign_subject_id, b.schoolname, c.teachername
, d.classname, e.subjectName, a.session
from my_table a
inner join school_table b on a.school_id = b.school_id
inner join teacher_table c on a.teacher_id = c.teacher_id
inner join class_table d on a.class_id = d.class_id
inner join subject_table e on a.subject_id = e.subject_id
LEFT JOIN if the relation key can not match
select a.assign_subject_id, b.schoolname, c.teachername
, d.classname, e.subjectName, a.session
from my_table a
left join school_table b on a.school_id = b.school_id
left join teacher_table c on a.teacher_id = c.teacher_id
left join class_table d on a.class_id = d.class_id
left join subject_table e on a.subject_id = e.subject_id

Using MySQL for relationnal division

I need to execute a query with a relationnal division
What I have : 2 tables with a 3rd table for Many-to-Many relation
=> Meetings have multiple participants and participants can attend multiple meetings
What I need : get the meetings which have at least the given participants
Here a SQL query which do the job :
SELECT
m.meeting_id,
m.name,
m.status
FROM meetings As m
INNER JOIN meetings_participants AS mp ON m.meeting_id = mp.meeting_id
WHERE m.status <> 'temporary'
AND mp.participant_id IN (1, 2)
GROUP BY m.meeting_id
HAVING COUNT(DISTINCT mp.participant_id) >= 2
SQL Fiddle : http://sqlfiddle.com/#!9/8a331d/6/0
Question 1 : is there a way to select what I need without the 'HAVING COUNT...' part ?
Question 2 : and in a second query, I need the meetings with exactly the given participants, how to do it ?
Question 1 : is there a way to select what I need without the 'HAVING
COUNT...' part ?
Yes you can use multiple JOIN's but that isn't a very good solution.because you need a JOIN for every mp.participant_id... The Query you have is much more scalable
Query
SELECT
m.meeting_id
, m.name
, m.status
FROM
meetings AS m
INNER JOIN meetings_participants AS mp1 ON m.meeting_id = mp1.meeting_id AND m.status <> 'temporary' AND mp1.participant_id = 1
INNER JOIN meetings_participants AS mp2 ON m.meeting_id = mp2.meeting_id AND m.status <> 'temporary' AND mp2.participant_id = 2
Result
| meeting_id | name | status |
|------------|-----------|-----------|
| 1 | a meeting | active |
| 5 | e meeting | cancelled |
demo http://sqlfiddle.com/#!9/8a331d/54
Question 2 : and in a second query, I need the meetings with exactly
the given participants
You need to find the COUNT first for every meeting_participants HAVING two records
With
SELECT
meeting_id
FROM
meetings_participants
GROUP BY
meeting_id
HAVING COUNT(*) = 2
And use that within the main query like so.
Query
SELECT
meetings.*
FROM (
SELECT
meeting_id
FROM
meetings_participants
WHERE
participant_id IN(1, 2)
AND
meeting_id IN(
SELECT
meeting_id
FROM
meetings_participants
GROUP BY
meeting_id
HAVING COUNT(*) = 2
)
GROUP BY
meeting_id
HAVING COUNT(*) = 2
)
meetings_participants
INNER JOIN
meetings
ON
meetings_participants.meeting_id = meetings.meeting_id
Result
| meeting_id | name | status |
|------------|-----------|-----------|
| 5 | e meeting | cancelled |
demo http://sqlfiddle.com/#!9/8a331d/46

mysql group by and take specific record from right join table

I have database with following data structure with sample data. Each company have multiple members. The relationship is in the company_member table. Please note only required fields I have given below.
company
id title
1 company-1
2 company-2
company_member
companyid memberid
1 1
1 2
1 3
2 4
2 5
2 6
member
id firstname member_type_id
1 Name-1 2
2 Name-2 3
3 Name-3 3
4 Name-4 3
5 Name-5 2
6 Name-6 1
member_type
id user_level
1 0
2 1
3 2
I want list of unique companies with one member from each. But the member should be the lowest user_level within the company. i.e, following result should come;
result
companyid company_title memberid member_name user_level
1 company-1 1 Name-1 1
2 company-2 6 Name-6 0
I want to know how to get one member with lowest user level among the same company.
This is a bit complicated one, however this is one way of doing it using not exists, for bigger tables its wise to use not exits since using pivot tables it will not use index.
select
c.id,
c.title,
m.id as member_id,
m.firstname,
mt.user_level
from company_member_map cmp
join company c on c.id = cmp.companyid
join member m on m.id = cmp.memberid
join member_type mt on mt.id = m.member_type_id
where not exists
(
select 1 from company_member_map t1
join member t2 on t2.id = t1.memberid
join member_type t3 on t3.id = t2.member_type_id
where
t1.companyid = cmp.companyid
and t3.user_level < mt.user_level
)
DEMO
Finally I found solution:
select c.id companyid, c.title company_title, m.firstname member_name, mt.user_level
from company c
inner join company_member cm on cm.companyid = c.id
inner join member m on m.id = cm.memberid
inner join member_type mt on mt.id = m.member_type_id
inner join
(select c1.id companyid, mt1.user_level
from company c1
join company_member cm1 on cm1.companyid = c1.id
join member m1 on m1.id = cm1.memberid
join member_type mt1 on mt1.id = m1.member_type_id
group by c1.id,m1.id
order by user_level asc
) sq on c.id = sq.companyid and sq.user_level = mt.user_level
group by c.id;
Correct this, if anyone have better solution or simplified solution.
Check this SQL Fiddle

MYSQL return results where there exist at least one from the other table

Say I have these data from two table:
Student Table columns:
id | name
Course Table columns:
id | code | name
and I want to use the Student.id AS Student and Course.id AS Course
to get the following:
Student | Course
-----------------
1 | C
1 | B
1 | A
2 | F
2 | B
2 | A
3 | C
3 | B
3 | F
How would I query it so it will return only the Students with a Course C and their other Courses like below:
Student | Course
-----------------
1 | C
1 | B
1 | A
3 | C
3 | B
3 | F
?
I have tried :
SELECT Student.id, Course.code FROM Course
INNER JOIN Student ON Course.student = Student.id
WHERE Course.code = 'C'
but I got only
Student | Course
-----------------
1 | C
3 | C
SELECT s.id, c.code
FROM Course c
INNER JOIN Student s
ON c.student = s.id
WHERE EXISTS
(
SELECT 1
FROM Course c1
WHERE c.student = c1.student
AND c1.Course = 'C'
)
The most efficient approach to this problem is usually an inline view and a JOIN operation, although there are several ways to get an equivalent result.
SELECT Student.id
, Course.code
FROM ( SELECT c.Student
FROM Course c
WHERE c.code = 'C'
GROUP BY c.Student
) o
JOIN Course
ON Course.Student = o.Student
JOIN Student
ON Student.id = Course.Student
Here, we're using an inline view (aliased as o) to get a list of Student taking course code = 'C'.
(NOTE: the query in my answer is based on your original query. If there's a foreign key definition between Course and Student, and we only need to return the Student.id, we could improve performance by omitting the join to Student, and return Course.Student AS id in place of Student.id in the SELECT list.)
Here the first JOIN selects only those students which have course C, and second JOIN gives you all the courses for each of those students.
SELECT st.id, c2.code FROM
Student st
JOIN Course c ON c.student = st.id AND c.code = "C"
JOIN Course c2 ON c2.student = st.id
You actually don't even need two tables here, because both student and course is available in the Course table, just JOIN it on itself:
SELECT c2.student, c2.code FROM
Course c JOIN Course c2 ON c.student = c2.student
WHERE c.course = "C"
Here the WHERE clause leaves student id's which have course C and then you JOIN those to find all their courses.

Pass value from query 1 to query 2

I have a query join 2 table as below:
SELECT * FROM Staff s INNER JOIN Account a on s.AccNo = a.AccNo WHERE a.Status = 'Active'
The result as shown:
AccNo | Name | ID
------------------
1 | Alex | S01
2 | John | S02
After I get the staff ID,I write second query to find out the max sale as below:
SELECT s.ProductID,Max(s.Amount) from Sales s WHERE StaffID = 'S01' GROUP BY s.ProductID
The max sale for Staff 'S01' as below:
ProductID | Amount
------------------
Cloth | 2000
How to I combine these 2 queries and become result as below? Thanks
AccNo | Name | ID | Amount
--------------------------
1 | Alex | S01 | 2000
2 | John | S02 | 5000
You can create a subquery and join it:
SELECT a.AccNo, b.Name, b.ID, c.maximum
FROM transaction as a
INNER JOIN Account as b
ON a.AccNo = b.AccNo
LEFT JOIN (SELECT StaffID, Max(Amount) as maximum FROM Sales GROUP BY StaffID) as c
ON c.StaffID = b.ID
WHERE b.Status = 'Active'
See the SQLFiddle example (I've tried to guess the schema)
So what you want to do is join to sales on the staffId then group.
SELECT a.AccNo,a.Name,a.ID,Max(s.Amount)
FROM Transaction t
INNER JOIN Account a on t.AccNo = a.AccNo
INNER JOIN Sales s on s.staffId = a.ID
WHERE a.Status = 'Active'
GROUP BY a.AccNo,a.Name,a.ID
You could try something like this:
Select Account.*, Max(Sales.amount) from Sales
JOIN Account ON Sales.StaffID = Account.ID
where Account.status = 'Active'
group by Sales.ProductID, Account.AccNo, Account.Name, Account.ID
Honestly, I don't understand why do you use Transascation table in your queries, because you don't use it.
I think this should work
Just do a join and retrieve the max amount associated with each staff
SELECT t.AccNo , t.Name, t.ID, s.ProductID, Max(s.Amount) FROM Transaction t
INNER JOIN Account a ON t.AccNo = a.AccNo
INNER JOIN Sales s ON s.StaffID = a.ID
WHERE a.Status = 'Active';
Thanks