How to make query to show result of single recursive request? - mysql

I have the structure of the table called person,
the person has: id,first_name,last_name,mother_id,father_id
I want to build a simple query that shows data of person
like this: id,first_name,last_name,father_first_name,mother_first_name
CREATE TABLE PERSON
(
ID varchar(20),
FIRST_NAME varchar(20),
LAST_NAME varchar(20),
PHONE_NUMBER varchar(20),
BIRTH_DATE DATE,
FATHER_ID varchar(20),
MOTHER_ID varchar(20),
PRIMARY KEY (ID),
FOREIGN KEY (FATHER_ID) REFERENCES PERSON(ID),
FOREIGN KEY (MOTHER_ID) REFERENCES PERSON(ID)
);

You can query this information simply by joining the table to itself and using a table alias. Recursion is not necessary unless the hierarchy you are navigating has a varying depth. For this question there is a fixed depth and you simply wish to see the parent child relationship between 2 records. The LEFT JOIN will ensure that even if you don't have both of the parents in your database, the record will still show for that person.
SELECT
P.ID
, P.FIRST_NAME
, P.LAST_NAME
, F.FIRST_NAME FATHER_FIRST_NAME
, M.FIRST_NAME MOTHER_FIRST_NAME
FROM
PERSON P
LEFT JOIN
PERSON F ON (P.FATHER_ID = F.ID)
LEFT JOIN
PERSON M ON (P.MOTHER_ID = M.ID)

Related

MySQL: How do I get to a column of another table via a mapping table

I am trying to create a database for assignments where there is a table for the tasks, a table for the persons and a table for the assignment of a person to a task.
Now I have tried to access the task table with a select statement and at the same time get all assigned persons but nothing worked. (because a task is also assigned to other tables)
Is there a way or do I have to use several statements for this?
This is how i created my Tables:
CREATE TABLE Locations (ID INT AUTO_INCREMENT, LocationID VARCHAR(255),
PRIMARY KEY (ID));
CREATE TABLE Persons (ID INT AUTO_INCREMENT, FirstName VARCHAR(255), LastName
VARCHAR(255), PRIMARY KEY (ID));
CREATE TABLE Tasks (ID INT AUTO_INCREMENT , TaskName VARCHAR(255), LocationID
INT, PRIMARY KEY (ID),
FOREIGN KEY (LocationID) REFERENCES Locations(ID));
CREATE TABLE Assinment (TaskID INT, PersonID INT,
PRIMARY KEY (TaskID, PersonID), FOREIGN KEY (TaskID)
REFERENCES Tasks(ID), FOREIGN KEY (PersonID)
REFERENCES Persons(ID));
And this is the UML.
I do not want my joins on the Assinment table like
SELECT (FirstName, LastName, TaskName) FROM ((Assinment INNER JOIN Tasks ON
Assinment.TaskID = Tasks.ID) INNER JOIN Persons ON Assinment.PersonID =
Persons.ID)
because the tasks table has more joins (e.g. locations and priorities) so i want my query start with
SELECT (ID, TaskName, FirstName, LastName, LocationName) FROM Tasks [...]
so i can get all data by id of the task
The Output then should give me this table.
Thanks for help :)
EDIT
Ouput added and desired input is now more specified
You can try subqueries :
SELECT column-names
FROM table-name1
WHERE value IN (SELECT column-name
FROM table-name2
WHERE condition)

sql statement not working getting errors

I am having some trouble getting a statement to run, I am looking for the total credits of each student and the student ID.
I have written:
select student.ID,sum (course.credits)
from (student natural join takes),course
where takes.course_id=course.course_id
group by student.ID
when I run this I get the following error:
column used in NATURAL join cannot have qualifier
my tables are
create table student
(ID varchar(5),
name varchar(20) not null,
dept_name varchar(20),
tot_cred numeric(3,0) check (tot_cred >= 0),
primary key (ID),
foreign key (dept_name) references department
on delete set null
create table takes
(ID varchar(5),
course_id varchar(8),
sec_id varchar(8),
semester varchar(6),
year numeric(4,0),
grade varchar(2),
primary key (ID, course_id, sec_id, semester, year),
foreign key (course_id,sec_id, semester, year) references section
on delete cascade,
foreign key (ID) references student
on delete cascade
I am not sure what the problem is. when I run this statement it works
select name, sum(course.credits)
from (student natural join takes),course
where ID=1000 and takes.course_id=course.course_id
group by name
if you can point me in the right direction I would appreciate it.. thank you
NATURAL JOIN is not recommended and can lead to subtle unintended bugs, particularly when tables are modified later. Use INNER JOIN instead:
select name, sum(c.credits)
from student s
inner join takes t
ON t.ID = s.ID
inner join course c
ON c.COURSE_ID = t.COURSE_ID
where s.ID = 1000
group by name
Best of luck.
The from clause is just wrong with regard to how you use your brackets. Just use an explicit join clause for all your joins and you should be OK:
SELECT student.ID, SUM(course.credits)
FROM student
NATURAL JOIN takes
NATURAL JOIN course
GROUP BY student.ID

mysql select query from multiple tables returns duplicate results

If this question is a little vague just let me know and I will provide more info.
I have written a query that gets data from multiple tables but it isn't working how I expected it too and I am completely stumped.
Here is my code:
SELECT students.student_fname, students.student_lname
FROM students, enrolments
WHERE enrolments.courseID = 'C001';
but this just returns all of the students first and last names in the students table and these names are displayed twice.
Here is the code for the two tables:
CREATE TABLE students
(
studentID CHAR(10) NOT NULL,
student_fname VARCHAR(15) NOT NULL,
student_lname VARCHAR(15) NOT NULL,
DOB VARCHAR(10) NOT NULL,
CONSTRAINT pk_students PRIMARY KEY (studentID)
);
CREATE TABLE enrolments
(
enrolmentNo int NOT NULL AUTO_INCREMENT,
studentID CHAR(10) NOT NULL,
courseID CHAR(4) NOT NULL,
CONSTRAINT pk_enrolments PRIMARY KEY (enrolmentno),
FOREIGN KEY (studentID) REFERENCES students (studentID),
FOREIGN KEY (courseID) REFERENCES courses (courseID)
)ENGINE = INNODB;
This is because you've not defined how students relate to enrolments.
You either need to use an inner join or add a where clause that show how they relate.
For example:
FROM Students
INNER JOIN enrolments on Students.ID = enrolments.studentID
Or
FROM students, enrolements
WHERE enrolments.studentID = students.ID
The first method is newer and preferred by many; but the legacy method is also supported.
To gain a better understanding of table joins take a look at this most excellent article: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
Otherwise you get what is called a Cartesian product of the two tables all data relates to all data.
If you do not have a unique index on enrolements (a student can only have 1 class enrolment) then a select Distinct field names or where... group by fields will also limit your results to close to what you're looking for as well.
============================ in response to follow-up comment===================
SELECT S.student_fname, S.student_lname
FROM students S
INNER JOIN enrolments E
ON S.StudentID = E.StudentID
WHERE e.courseID = 'C001'
GROUP BY S.Student_Fname, S.Student_lname
ORDER BY S.Student_LName, S.Student_FName
The group by eliminates duplicates for the same course.
The "ON statement tells the database how students relates to enrolments.
The order by is just to provide a reasonable order to results.
You cannot fetch data from two tables in this way. You have to join tables.

Using the same table, and attributes to return different types of people

I am wanting to create a query that returns a parent and its guardian using the follow tables. My question is how can I use the name attribute in the person table twice to return the name of the caregiver and the name of the parent. Any example code would be appreciated thanks. I know I haven't explained it very well as but if anyone understand what I mean feel free to edit the above. More specifically I want to use only the person table to store information about parents and their children and use display the name of each who are related. How can I do this with a single table.
Using some advice provided, I was able to create the query but due to a problem with my table it doesn't work. I am using the following tables:
CREATE TABLE Person
(
personID INT NOT NULL,
name VARCHAR(50),
address VARCHAR(70),
phone VARCHAR(15),
email VARCHAR(30),
year INT,
PRIMARY KEY (personID)
);
CREATE TABLE Guardian
(
parentID INT NOT NULL,
childID INT NOT NULL,
PRIMARY KEY (parentID, childID)
FOREIGN KEY (parentID) REFERENCES (personID),
FOREIGN KEY (childID) REFERENCES (personID)
);
What statements should I use where to get this to work properly. I think the problem is that both foreign key statements are referring to the same key in the person table. How do I refer to the same attribute when looking for both the parent and child without getting any errors.
You can join with a table twice, but you must use different table aliases.
Try this:
SELECT
Child.name,
Parent.name
FROM Person AS Child
JOIN Guardian
ON Child.personID = Guardian.child
JOIN Person AS Parent
ON Parent.personID = Guardian.parent
I couldn't understand what u are looking for, anyway Try this:
select p.name,p.name from person p where p.personid in (select
distinct parentid from guardian )

Mysql foreign key

I want to make a link between a table customer and a table product by an IdProduct.
Example:
Create table customer(
idcustomer INT not null,
name Varchar(20),
idproduct INT,
);
create table Product(
idproduct INT not null,
nameProduct varchar(40)
);
How can I link the two together like the foreign key system for, when I select a customer, I can get all his products? It's a question about the structure of the database.
You want to introduce a 3rd table to resolve the many-to-many relationship between customers and products. It should consist of idcustomer and idproduct.
Then, to get all the products for a given customer:
SELECT c.name, p.nameProduct
FROM Customer c
INNER JOIN CustomerProductXref cpx
ON c.idcustomer = cpx.idcustomer
INNER JOIN product p
ON cpx.idproduct = p.idproduct
WHERE c.idcustomer = 12345
In mysql a foreign key is a special type of constraint. It is preferably created with the table, but can also be added afterwards. In this case, you might define the constraint as:
ALTER TABLE customer
ADD FOREIGN KEY (idproduct)
REFERENCES Product (idproduct);
(Note that you have to use the InnoDB engine to take advantage of FK's in mysql. More here
However FK's aren't required to make a JOIN, which is how you would link the tables in a SELECT -
select c.idcustomer, c.name, p.nameproduct
from customer c
join Product p on p.idproduct=c.idproduct;
Here's how you'd make a foreign key constraint (ignoring the cardinality issues that Joe rightly suggests):
CREATE table Product(
idproduct INT not null,
nameProduct varchar(40),
PRIMARY KEY (idproduct )
);
CREATE table customer(
idcustomer INT not null,
name Varchar(20),
idproduct INT,
FOREIGN KEY (idproduct) REFERENCES Product(idproduct )
);
Get your data like this:
SELECT * FROM Product AS P
INNER JOIN Customer AS C ON C.idproduct = P.idproduct
WHERE C.idcustomer = 1