Jump to content

Best way to design these tables and query them?


GuitarGod
Go to solution Solved by Barand,

Recommended Posts

Hi all,

 

I'm after some advice about these tables and whether I'm using them in the most efficient way.

 

Currently I have 4 tables; Students, Schools, Administrators and School members.

 

The Students table is simply a list of students with an 'admin_id' field - which relates to an administrator in the Administrators table who created the student (the student may not yet be a member of any School as explained further in the Schools and School members tables).

STUDENTS

+---------------+---------------+---------------+
| Student ID    | Admin ID      | Student name  |
+---------------+---------------+---------------+
| 1             | 1             | Mike          |
| 2             | 1             | Edward        |
| 3             | 1             | John          |
| 4             | 1             | George        |
+---------------|---------------+---------------+

The Administrators table contains the people who will use the script and oversee the Students/Schools table

ADMINISTRATORS

+---------------+---------------+
| Admin ID      | Admin name    | 
+---------------+---------------+
| 1             | Mr James      | 
| 2             | Mr Davies     | 
| 3             | Ms Lewis      | 
| 4             | Mrs Walsh     | 
+---------------|---------------+

Just from the example above, you can see that all current students have been registered by Mr James.

 

The Schools table, similar to the Students table, is simply a list of Schools registered by an administrator (containing an 'admin_id' related field).

SCHOOLS

+---------------+---------------+---------------+
| School ID     | Admin ID      | School name   |
+---------------+---------------+---------------+
| 1             | 1             | Hilbre        |
| 2             | 1             | Ridgeway      |
| 3             | 2             | Grammar       |
| 4             | 2             | Calday        |
+---------------|---------------+---------------+

From the above example, Administrator Mr James has registered Schools Hibre and Ridgeway, whilst Mr Davies has registered schools Grammar and Calday.

 

Now, for the complicated part that I'm struggling with. Administrators and Students should be interchangeable. For example, Administrator Mr James may 'belong' to any School created by Mr Davies - as may any of his students. I've tried to keep track of Administrators/Students/Schools by using a School members table.

SCHOOL MEMBERS

+---------------+---------------+---------------+
| *Member type  | Member ID     | School ID     |
+---------------+---------------+---------------+
| 1             | 1             | 1             |
| 1             | 2             | 2             |
| 1             | 1             | 2             |
| 0             | 2             | 2             |
+---------------|---------------+---------------+

* 0 = Student
  1 = Administrator

Without trying to complicate matters, the table above shows that Mr James and one of his students are both members of a School registered by a different administrator.

 

The query I'm trying to write would be; If I'm logged in as Mr James (or any other administrator), I'd like to query these tables to get a list of students that I've created, students that belong to my schools AND students that belongs to other schools that I'm a member of. I hope that makes sense and I hope I haven't over complicated it - is there's any easier way to handle this data, I'm all ears!

 

EDIT:

 

In the above query, I'd also need a GROUP_CONCAT list of Schools that the student belongs to (if they belong to any) if possible!

 

Thanks for any help :happy-04:

Edited by GuitarGod
Link to comment
Share on other sites

Lets start with the DB design. What are Students and what are Administrators? They are People. Depending on exactly what your doing and what you may do in the future, you could have problems splitting 'People' into two tables which it seems you are already at.

 

Students and Administrators are roles the people play. It is very possible for an Administrator to be a Student and a Student to be an Administrator. The result of that would be duplicating data which violates Database Normalization.

 

What you would want to do is have a 'persons' table with all the people in it, a role table with Administrator and Student as role options,  person_role table with the person.person_id and role.role_id. This will allow for unlimited persons with unlimited roles to grow infinitely just by adding a new person and a new role.

 

Get to this point and we can go from there.

Edited by benanamen
Link to comment
Share on other sites

I agree with Benanamen. The model I used assumes a member can have only one role (Admin or Student) and is attached. The query to get your list would be a union of the three types of selection that you want.

--
-- select students created by Admin #10
--
SELECT member_name
FROM members
WHERE created_by = 10
AND role_id = 2
UNION
--
-- select students from schools
-- created by admin #10
--
SELECT member_name
FROM members m 
INNER JOIN school_members sm USING (member_id)
INNER JOIN schools s USING (school_id)
WHERE s.created_by=10
AND m.role_id = 2
UNION
--
-- select students from schools
-- where admin #10 is a member
--
SELECT member_name
FROM members m 
INNER JOIN school_members sm1 ON m.member_id = sm1.member_id
INNER JOIN school_members sm2 ON sm1.school_id = sm1.school_id
WHERE sm2.member_id = 10
AND m.role_id = 2
;

post-3105-0-58406400-1451866698_thumb.png

Link to comment
Share on other sites

Thank you both sincerely! I've taken your advice Benanamen and changed the tables accordingly.

 

And Barand, as ever, your code is spot on :happy-04:

 

I've been trying to add a GROUP_CONCAT to the query so that if a student belongs to any schools, the school ID and name are returned. I'm not having much luck but I'll keep trying. Out of interest, is there an easy way to achieve this?

 

Thanks once again for all your advice/help!

Link to comment
Share on other sites

  • Solution

Yes.

SELECT member_name
, studs.member_id
, GROUP_CONCAT(school_name, '(', s.school_id, ')' SEPARATOR ', ') as schools
FROM
	(
	SELECT member_name
	, member_id
	FROM members
	WHERE created_by = 10
	AND role_id = 2
	UNION
	--
	-- select students from schools
	-- created by admin #10
	--
	SELECT member_name
	, m.member_id
	FROM members m 
	INNER JOIN school_members sm USING (member_id)
	INNER JOIN schools s USING (school_id)
	WHERE s.created_by=10
	AND m.role_id = 2
	UNION
	--
	-- select students from schools
	-- where admin #10 is a member
	--
	SELECT member_name
	, m.member_id
	FROM members m 
	INNER JOIN school_members sm1 ON m.member_id = sm1.member_id
	INNER JOIN school_members sm2 ON sm1.school_id = sm1.school_id
	WHERE sm2.member_id = 10
	AND m.role_id = 2
	) studs
LEFT JOIN school_members USING (member_id)
LEFT JOIN schools s USING (school_id)
GROUP BY member_name
;
  • Like 1
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.