How to get a tripple self-join working - mysql

I am trying to self join information from a table, to show a hierarchy (the table contains members, which consist of children and their parents). The table name is ‘members’, the four important columns are id, full_name, father_id and mother_id. The id's in the columns father_id and mother_id match the corresponding id's in column 'id'. As a result of the query, I would like to have a table with three columns, with column names 'Name', 'Father' and 'Mother'
I searched google, w3 schools and stack overflow, the closest to what I was looking for was a topic I found right here, called ‘Explanation of self-joins’ that had the following example code:
select
c1.Name , c2.Name As Boss
from
emp1 c1
inner join emp2 c2
on c1.Boss_id = c2.Id
I altered the query as follows (I didn't even dare include the third column yet :') ):
select
c1.full_name as Name, c2.full_name as Father
from
members1 c1
inner join members2 c2
on c1.father_id = c2.id
Unfortunately, I got an error message stating the following: 1146 - Table 'ppstb.members1' doesn't exist
I guessed it had something to do with how I simulated having two tables. The next thing I experimented with is:
select
c1.full_name , c2.full_name as Father
from
members c1, members c2
inner join members c2
on c1.father_id = c2.id
But this also gives an error: 1066 - Not unique table/alias: 'c2' What step am I missing?

last member should be c3 not c2
select
c1.full_name , c3.full_name as Father
from
members c1, members c2
inner join members c3
on c1.father_id = c3.id

I actually got the code working, using left-joins. I'm not sure why the inner joins wouldn't work, but this solved my problem:
SELECT
members.full_name, b.full_name AS Father, c.full_name AS Mother
FROM
members
LEFT JOIN
members b ON (members.father_id = b.id)
LEFT JOIN
members c ON (members.mother_id = c.id)

Related

"where" on joined field in a left join

I'd like to make a self join which I did using LEFT JOIN but now I'd like to join 2 other tables and add a where on 2 of the fields of the joined table. The data table contains a self reference to its parent ID. I'd like to get the child name AND the parent name for a given CATEGORY and TYPE. I tried the following request:
SELECT d1.NAME as NAME, d1.Parent as Parent, d2.NAME as PARENT_NAME
FROM data as d1 LEFT OUTER JOIN data as d2 ON d1.PARENT = d2.ID
JOIN TYPE ON d1.T_ID
JOIN CATEGORY ON d1.CAT_ID
WHERE TYPE_NAME = 'Name'
AND CAT_NAME = 'Name'
But the result is the same with out without the "where" meaning that I get all the result for all CATEGORY and all the TYPE.
Your JOIN conditions are incomplete, so you are effectively getting a CROSS JOIN instead since wherever T_ID and CAT_ID are not 0 or NULL a JOIN will happen. Try changing them to (assuming the ID columns in the TYPE and CATEGORY tables are called ID):
JOIN TYPE ON d1.T_ID = TYPE.ID
JOIN CATEGORY ON d1.CAT_ID = CATEGORY.ID
Please correct your join condition at the time of joining
SELECT d1.NAME as NAME, d1.Parent as Parent, d2.NAME as PARENT_NAME
FROM data as d1
LEFT OUTER
JOIN data as d2 ON d1.PARENT = d2.ID
JOIN TYPE ON d1.T_ID **= someColumn**
JOIN CATEGORY ON d1.CAT_ID **= someColumn**
WHERE TYPE_NAME = 'Name'
AND CAT_NAME = 'Name'

Two tables. One contains the school info and the other personal. A quire that picks students who are from CA and like either skateboard or soccer.

What currently happens is it just selects students from CA and students who like to skateboard. I need it to return only students who are both from CA and play soccer.
SELECT *
FROM schooldata a
INNER JOIN studentinfo b
ON b.schooldata_id = a.id
WHERE a.state = "ca"
AND ( activity = "soccer"
OR activity = "skateboard" )
You will have to do inner join based on lastname and firstname column ex:-b.lastname=a.lastname and b.firstname=a.firstname . ideally you should be maintaining primary key column of type integer in schooldata table and its foreign key reference in studentinfo and join based on those columns.
You should use join clauses. And I think base on your question. Inner Join is the best clause you should use.
SELECT column_name(s)
FROM table1
INNER JOIN table2 ON table1.column_name = table2.column_name;

SQL: Returning a list of all the classes that 2 specific students are both attending

I've tried all I can to figure this one out, hopefully someone here can help.
I'm given the database schema as follows:
Customer: ID FirstName LastName DateOfBirth
Instructor: Id FirstName LastName
FitnessClass: Id ClassName Cost InstructorId
Subscription: CustomerId ClassId StartDate
With the question being:
Retrieve a list of all classes (Id and ClassName) that both Joe Bloggs and John Snow have subscribed to (ie Joe Bloggs and John Snow have been in the same Fitness Class).
My attempts have only produced all classes that either are in, not only the classes that both are in.
My attempt:
SELECT fitnessclass.id, fitnessclass.classname
FROM fitnessclass
LEFT JOIN subscription ON fitnessclass.Id = subscription.ClassID
LEFT JOIN customer ON subscription.CustomerID = customer.ID
WHERE customer.ID IS NOT NULL
AND customer.FirstName IN ("Joe", "Bloggs")
We want the c.ClassId and c.ClassName values from DISTINCT rows where:
class c.Id is named c.ClassName and costs c.Cost and is taught by c.InstructorId
AND customer c1.ID is named c1.FirstName c1.LastName and was born on c1.DateOfBirth
AND customer c2.ID is named c2.FirstName c2.LastName and was born on c2.DateOfBirth
AND c1.ID <> c2.ID
AND customer s1.CustomerId subscribed to s1.ClassId starting on s1.StartDate
AND customer s2.CustomerId subscribed to s2.ClassId starting on s2.StartDate
AND c1.ID = s1.CustomerId AND c2.ID = s2.CustomerId
AND c1.FirstName = 'Joe' AND c1.LastName = 'Bloggs'
AND c2.FirstName = 'John' AND c2.LastName = 'Snow'
AND s1.ClassId = c.ClassId AND s2.ClassId = c.ClassId
Observe that an aliased table with no duplicates holds (the set of) rows that make a true statement from a statement template (predicate) associated with its base table by the database designer:
-- class c.Id is named c.ClassName and costs c.Cost and is taught by c.instructorId
FitnessClass c
-- cx.ID is named cx.FirstName cx.LastName and was born on cx.DateOfBirth
Customer cx
-- customer sx.CustomerId subscribed to class sx.ClassId starting on sx.StartDate
Subscription sx
Observe also that if expression L holds the rows satisfying templateL and expression R holds the rows satisfying templateR then
L JOIN R holds the rows satisfying templateL AND templateR
R WHERE condition holds the rows satisfying templateR AND condition
templateR ON condition holds the rows satisfying templateR AND condition
So the rows we want to SELECT from are:
FROM Class c
JOIN Customer c1 JOIN Customer c2
ON c1.ID <> c2.ID
JOIN Subscription s1 JOIN Subscription s2
WHERE
AND c1.ID = s1.CustomerId AND c2.ID = s2.CustomerId
AND c1.FirstName = 'Joe' AND c1.LastName = 'Bloggs'
AND c2.FirstName = 'John' AND c2.LastName = 'Snow'
AND s1.ClassId = c.ClassId AND s2.ClassId = c.ClassId
Conditions can be in ANDed any order as long as each only uses columns from a preceding JOIN or JOIN ON. So you can rearrange these in some other order if you think it better. (Eg to localize the use of some column names.) (But arguments that you must organize via ON (or that "," is inappropriate) are specious.)
DISTINCT removes duplicate rows after dropping the non-SELECTED columns from the table that the FROM etc produces. This is so that the result holds the set of rows that satisfy its template. DISTINCT isn't always necessary. But you still want distinct rows. In general you have to think about whether you can avoid DISTINCT. Sometimes you can't. Sometimes you can reason that what you do next with a table with duplicates gives the same answer whether or not there are duplicates. Rarely, the requested result is permitted to have or is supposed to have duplicates. But then you can't use that result further while reasoning via the simple relational-template expression correspondence. (Exercise: Show whether there is a SELECT returning the right classId & className values from the FROM etc table without DISTINCT.)
(It's not clear why you think that LEFT JOIN is appropriate. It returns what JOIN does but with unmatched left table rows extended by NULLs.)

Join from 2 tables using foregin key MySql

hello I am trying to join a table Classes & Employee together by using the foreign key "Employee_Id" from the C table to get the first and last name from the E table
SELECT class_id,
subject_name,
classes.employee_id
FROM schooladmindb.classes
INNER JOIN schooladmindb.employee
ON
where classes.employee_id = employee.employee_id;
Im unsure of the statement I would have to use to just gain "First_Name" & "Last Name" From the E table which keeping the C table data intact
Your statment is wrong because you dont need the WHERE to join both tables
Check JOIN sintaxis
SELECT class_id,
subject_name,
classes.employee_id
FROM schooladmindb.classes
INNER JOIN schooladmindb.employee
ON classes.employee_id = employee.employee_id;
Yes you can simply add first name and last name along with other fields like
SELECT class_id,
subject_name,
employ_FirstName, // Column in your employee table
employ_LastName,
classes.employee_id
FROM schooladmindb.classes
INNER JOIN schooladmindb.employee
ON classes.employee_id = employee.employee_id;

select categories with parent name from one table

I got an existing products database which I'm writing an administration tool for (in PHP).
The database contains the following "categories" table:
Table Categories
--------------------
PK | id
FK | parent_id
| title
Now the foreign key "parent_id" contains an id taken from the same table, or "0" if it's a topmost category.
For creating an overview I now need a mysql statement which results in the following data:
id | parent_id | title | parent_title
The parent_title is where I've no idea. I created the following statement:
SELECT
c1.id,
c1.parent_id,
c1.title,
c2.title as `parent_title`
FROM
categories c1,
categories c2
WHERE
c1.parent_id = c2.id
I now only get all categories which have got a parent category.
Should be simple, and might have already been answered here. I think I only didn't find the right words to search for to find it by searching existing articles.
Thanks for your help,
Daniel
You can use a LEFT OUTER JOIN for this:
SELECT c1.id,
c1.parent_id,
c1.title,
c2.title as `parent_title`
FROM categories c1
left outer join categories c2 on c1.parent_id = c2.id
you're looking for an OUTER JOIN :)
See here: http://www.quackit.com/sql/tutorial/sql_outer_join.cfm