Many to Many Relationship using Joins - mysql

I have a database two tables and a linking table that I need a JOIN query for:
Here are my Tables:
family (userid (int), loginName, etc)
member (memberid (int), loginName(this links member to a family),name, etc)
Linking Table:
user2member (userid,memberid)...would both be foreign keys?
I want to do two things:
1) Be able to have a family.loginName(12,Johnson) subscribe to another family.loginName (43,Smith) and record that into the linking table.
That would look like this:
12,43
2) When I do a query for all the member.name that are in the Johnson Family, I'll get all the Johnsons & all the Smiths.
If Johnson = Ted, Sue & Patty
IF Smith =Joe, Sue & Bob
my query results would be Johnson now = Ted,Sue,Patty,Joe,Sue,Bob
I asked this question a few days ago without good table names and I ended up confusing myself and the nice guy Ollie Jones who posted an answer similar to this for the query:
SELECT member.name
FROM family
JOIN user2member on family.userid = member.memberid
JOIN member on user2member.name = member.name
 WHERE family.userid = '30'
ORDER BY member.name
I had to change Ollie's answer to match my tables but I'm getting a limit error 0,30 on line 5.
This is my first time doing JOINS and I have no idea if this is correct.
Thanks,
Here's the link to my first question: mySQL table linking , group linked to other members lists, the displaying all members

I am not sure, if the tables you suggested would solve your problem. If I understand your question correct, there are two relationships:
a relationship for all family members (Johnson with Ted, Sue, Patty, Smith with Joe, Sue, Bob)
a relationship for subscriptions (a family can subscribe to another family)
I would suggest following tables:
family (f_id, f_loginName, etc.)
member (m_id, m_f_id, m_name) (foreign key to family, many-to-one relationship)
subscription (s_f_id,s_to_f_id) (linking is based on both family keys)
This would result in following contents:
family:
f_id f_loginName
12 Johnson
43 Smith
member:
m_id m_f_id m_name
1 12 Ted
2 12 Sue
3 12 Patty
4 43 Joe
5 43 Sue
6 43 Bob
subscription
s_f_id s_to_f_id
12 43
Now, to get all possible members for a specific family and it's subscriptions, I would use following SQL query. It has a simple join for family and it's family members. In the WHERE clause, the family Johnson is fetched (f_id = 12) and to get all family members from the subscriptions, it's easier to use a subquery.
SELECT f_loginName, m_name
FROM family
INNER JOIN member ON m_f_id = f_id
WHERE f_id = 12
OR f_id IN (SELECT s_to_f_id FROM subscription WHERE s_f_id = 12)
ORDER BY f_loginName, m_name;

Related

Select and compare two columns from different tables to find matched records

I'm just learning PHP and MySQL and I have two tables in the same database : FirstYear , SecondYear that have a structure like this :
StudentId |Math | Physics StudentId1 | Math1 | physics1
Joe 10 14 Alan 12 17
Alan 13 17 Smith 11 13
Smith 9 9 Joe 10 15
Is it possible to write a query that select and compare the two columns StudentId , StudentId1 to find matched records and if for example Joe=Joe after that compare records of math with math1 and physics with physics1 that are in the same row as matched records of StudentId with StudentId1 ;the idea of this query is to study the improvement of same student from first year to the second one ,Thanks .
Yes, it is possible but you have to complete SQL fundamental course.
In this situation you have to know about JOIN. Such as, Inner Join, Left Join, Right Join, Full Join etc. Also, compare with unique id, not name. Because, name always duplicate. It is not good practice. So, Know about primary key and foreign key.
However,
Query-
SELECT * FROM FirstYear INNER JOIN SecondYear ON FirstYear.StudentId = SecondYear.StudentId1 WHERE FirstYear.id = 1
Something like that, alternatively, you can try to another logic.

Which kind of join should i use? [EF4.0 code first ]

i apologize for the bad topic title as i am kinda at lost of what should i do here.
First of all, here are my database table designs and i would like to receive some sort of feedback as well before proceeding:
I am trying to make an enrollment web application.
Subjects
subject
[id] [subj] [professor] [cstart] [cend] [days] [count] [units]
1 comalgo carl 10:00am 12:30pm M-W 40 3.0
2 compasm carl 01:00pm 02:30pm T-TH 40 3.0
3 compro miguel 04:30pm 06:30pm M-W 35 3.0
4 pro5 fua 03:30pm 05:30pm T-TH 30 3.0
5 pro5 fua 06:30pm 08:30pm F 10 3.0
Students
students
[id] [fname] [lname] [bday] [unitsleft] [unitstaken] [major]
1 carlos doe 11/20/1990 100 0 BS-COMPUTER SCIENCE
2 miguel doe 08/15/1992 100 0 BS-ECONOMY
3 carl doe 12/12/1991 100 0 BS-PSYCHOLOGY
4 test doe 02/12/1992 100 0 BS-LITERATURE
What i plan on doing is that, the subjects will be presented through a series of list and the student will pick multiple subjects and enroll. The total enrolled units should not be greater than 20 and less than 11. I already implemented that part and i am now working on storing the selected subjects.
Here is my proposed solution and i would like to receive some feedbacks about it and what operation should i use.
I will have a centralized table for all of enrolled subjects
Enrolled subjects
selected subject
[id] [subjid] [studentid] [status]
1 1 1 P //comalgo enrolled by carlos, P is for pending grade
2 1 2 P //comalgo enrolled by miguel P is for pending grade
3 2 1 P //compasm enrolled by carlos P is for pending grade
What i plan to happen is that: i have a profile page for the students and they will be able to view/edit their currently enrolled subjects specifically for themselves(based from ID)
I want them to be presented with the following table headers which is based from the enrolled subjects:
[subj] [professor] [cstart] [cend] [days]
Here are the brief summary of my questions:
1.) is my table alright? or it's a bad design?
2.) What kind of method should i use? i am trying to research about it(joins) but i am somehow confused and in need of clarification. I want to present the users with their selected subjects.
edit: i think i can do something like.. select where id = x from the enrolled subjects then get the subject id but i am not sure if that will be efficient.
Your tables look good (i.e. third normal form). An INNER join will do
SELECT
B.subj, B.professor, B.cstart, B.cend, B.days
FROM
selectedsubjects A
INNER JOIN subjects B ON A.subjid = B.id
WHERE
A.studentid = 1
p.s. This looks like an assignment for school or something out of a book...?
It could be:
var query = context.EnrolledSubjects
.Include("Subject")
.Where(i => i.StudentId == 1)
.Select(i => new {
i.Subject.Subj,
i.Subject.Professor,
i.Subject.CsStart,
i.Subject.Send,
i.Subject.Days,
i.Status
};

mySql one to many relation table structures

Folks can you please give your suggestions for my question regarding mysql joins.
My Table structures:
place table:
place_id place_name city
1 Hotel Golconda Hyderabad
2 Paradise Hotel Hyderabad
3 Hotel Mayuri Hyderabad
place_tags
tag_id tag_name
1 Valet Parking
2 Air Conditioned
3 Buffet
4 Bar
5 Family Dining
places_info Table:
place_id tag_id
1 1
1 2
1 3
2 1
2 5
3 1
3 4
The above is all my tables which are containing the place names and address in places table, all the facilities of the restaurants in tags table and mapping of the facilities of each place in places_info table.
Is this my table structures are correct to get the places which had "Valet parking and Buffet". How can write a join query for this type of results to get.
Most Importantly we had millions of places in places table and also in the places_info table. How to achieve maximum performance with this type of table structure? Or shall I need to change the table structures?
Please guide me.
This'd be the basic structure for "places with valet AND buffet":
SELECT place_id, COUNT(places_info) AS cnt
FROM place
LEFT JOIN places_info ON place.place_id = places_info.place_ID
AND tag_id IN (1, 3)
^^^^---- two tags: valet(1) + buffet(3)
GROUP BY place.place_id
HAVING cnt = 2
^^^---- must have both tags
For a places which have NEITHER of the tags, or only one, the count would come back 0, or 1, and get dumped by the HAVING clause.

SQL Database with undefined columns

I'm working on a project where I'm dumping data into a mysql database about different people, however, each person can have many entries so I'm not sure how to have a lot of columns.
e.g
Name id
jack 234 01241990 13241990 03451993 10945
james 222 01131998 14242001 03414235 10945435 3456363 3465758
jill 1234 01131998 14242001 03414235 10945435 3456363 3465758 4253156316 6427247 583583
As you can see there can be many entries for each person, not in 100's, but I think the max can be around 20-30ish? So how do I build a database that I can insert values into without knowing how many entries will be per person, beforehand.
I am using perl script to insert values. Any ideas will be helpful
EDIT: People are suggesting to create two tables, however, when I joint he tables, I want one row for each person.
e.g After joining my view should look like
james 222 01131998 14242001 03414235 10945435 3456363 3465758
My suggestion would be to split the data into two tables (People and Data):
People:
NAME ID
Jack 234
James 222
Jill 1234
Data:
ID PeopleID Data
1 234 01241990
2 234 13241990
.
.
99 1234 6427247
100 1234 583583
You can then use joins to get the data for each person
SELECT p.Name,
p.ID,
d.Data
FROM People p
JOIN Data d
ON d.PeopleID = p.ID
ORDER BY p.Name --(assuming you want names in alphabetical order)
You should get something like the following
Name ID Data
Jack 234 01241990
Jack 234 13241990
.
.
Jill 1234 6427247
Jill 1234 583583

Getting data from multiple tables into single row while concatenating some values

I'm trying to retrieve data from tables and combine multiple rows into a single column, without repeating any information.
I have the following tables: profile, qualification, projects.
Profile
pro_id surname firstname
------ ------- ----------
1 John James
2 King Fred
3 Luxury-Yachts Raymond
Qualification
pro_id Degree School Year
------ ------ ------ -----
1 MBA Wharton university 2002
1 LLB Yale University 2001
2 BSc Covington University 1998
2 BEd Kellog University 1995
Projects
pro_id Title Year
------ ------ ------
1 Social Networking 2003
1 Excavation of aquatic debris 2007
2 Design of solar radios 1992
2 Development of expert systems 2011
I want to retrieve the all of the information for each person, with each person appearing only once in the result. The info on qualifications and projects should each be in their own column (one column for qualifications, another for projects), separated by commas. For example, the results for the above sample data should be:
1 John James MBA Wharton university 2002, LLB Yale University 2001 Social Networking 2003, Excavation of aquatic debris 2007, Design of Solar panels 2008
2 King Fred BSc Covington University 1998, BEd Kellog University 1995, Msc MIT 2011 Design of solar radios 1992, Development of expert systems 2011
3 Raymond Luxury-Yachts
Currently, I have the query:
SELECT pro_id,
surname,
firstname,
group_concat(degree,school,year) AS qual,
concat(Title,year) AS work
FROM profile,
LEFT JOIN qualification
ON qualification.pro_id = profile.pro_id
JOIN projects
ON projects.pro_id = profile.pro_id
GROUP BY pro_id
For the sample data, this query results in:
1 John James MBA Wharton university 2002, Social Networking 2003
1 John James LLB Yale University 2001, Excavation of aquatic debris 2007
1 John James MBA Wharton university 2002, Social Networking 2003, Excavation of aquatic debris 2007
etc
Note: Raymond Luxury-Yachts isn't present in the current result.
I don't want duplicate result records. Also if the surname does not have any entry in the qualification and projects table, I want the query to return the name and display an empty field in the qualification and projects table instead of omitting them altogether.
Replace LEFT JOIN with JOIN
Select pro_id, surname, firstname, group_concat(degree,school,year) as qual,concat(Title,year) as work
from profile
join qualification on qualification.pro_id = profile.pro_id
join projects on projects.pro_id = profile.pro_id group by pro_id
What is the difference between "INNER JOIN" and "OUTER JOIN"?
Using Join will fix the issue with displaying values even if there are no records in the projects table.
For the first question, you can try making a stored function and calling it from the select statement. This function will take pro_id as parameter, create the concatenated string and return it. That's the only solution for MySQL that I can think of at the moment.
I think you are close on your thoughts of group_concat. However, with possible No values (thus leaving nulls), can cause problems. I would have each secondary table pre-concatinated by person's ID and join to THAT result. Eliminates the problem of nulls
SELECT
p.pro_id,
p.surname,
p.firstname,
PreQConcat.UserQual,
PrePJConcat.UserWork
FROM
profile p
LEFT JOIN
( select q.pro_id,
group_concat( q.degree, q.school, q.year) AS UserQual
from
qualification q
group by
q.pro_id ) PreQConcat
ON p.Pro_ID = PreQConcat.pro_id
LEFT JOIN
( select pj.pro_id,
concat(pj.Title, pj.year) AS UserWork
from
projects pj
group by
pj.pro_id ) PrePJConcat
ON p.Pro_ID = PrePJConcat.pro_id
You are going through all people anyhow, and want all their respective elements (when they exist) grouped, so why group on a possibility it doesn't exist. Let the JOINED queries run once each, complete with a single result grouped by only those people it had data for, then join back to the original profile person.