Joins for queries - mysql

I am preparing for my exams this week and I saw a past paper question like this:
Lecturer
lec_id
lec_name
phone
dept
requests
lec_id
book_id
qty
date
book
book_id
title
author
cost
supplier
I need to write a MySQL command that will find the name and phone number of each lecturer requesting the book with id# 123.
I tried creating the query as shown below:
SELECT lec_name, phone FROm lecturer
LEFT JOIN requests ON requests.lec_id = lecturer.lec_id
LEFT JOIN requests ON requests.book_id = book.book_id
WHERE book.book_id = 123
However I keep getting the error Not unique table/alias: 'requests'

Best to start from the book so the WHERE clause is cleaner, and perhaps more intuitively adapted to searching for another specific book and/or all books:
select book.book_id, book.title, lecturer.lec_name, lecturer.phone
from book
left join requests on book.book_id = requests.book_id
left join Lecturer on requests.lec_id = Lecturer.lec_id
where book.book_id = 123

SELECT lec_name, phone FROm lecturer
LEFT JOIN requests ON requests.lec_id = lecturer.lec_id
AND requests.book_id = book.book_id
WHERE book.book_id = 123

Related

Why does my Query return "Empty set (0.00 sec)"?

SOLVED-run UPDATE building SET building_name = "Main Street Building" WHERE building_id = 2;
From there, the task 3 query will return proper results.
Task One:
Query:
SELECT first_name, last_name, building_name, room.room_id, meeting_start,meeting_end
FROM meeting, person, person_meeting,room, building
WHERE room.room_id=meeting.room_id
AND meeting.meeting_id=person_meeting.meeting_id
AND person.person_id=person_meeting.person_id
AND room.building_id=building.building_id
AND person.first_name='Tom'
AND person.last_name='Hanks';
Task Two:
Query:
SELECT first_name, last_name, building_name, room.room_id, meeting_start,meeting_end
FROM meeting, person, person_meeting,room, building
WHERE room.room_id=meeting.room_id
AND meeting.meeting_id=person_meeting.meeting_id
AND person.person_id=person_meeting.person_id
AND room.building_id=building.building_id
AND meeting.meeting_id=2;
Task Three:
Query:
SELECT first_name, last_name, building_name, room.room_id,meeting.meeting_id, meeting_start, meeting_end
FROM meeting, person, person_meeting,room, building
WHERE room.room_id=meeting.room_id
AND meeting.meeting_id=person_meeting.meeting_id
AND person.person_id=person_meeting.person_id
AND room.building_id=building.building_id
AND building_name='Main Street Building';
Task Four:
Query:
SELECT count(person_id) 'Count of meeting attendees', meeting.meeting_id,meeting_start,meeting_end
FROM meeting, person_meeting
WHERE meeting.meeting_id=person_meeting.meeting_id
GROUP BY meeting.meeting_id;
Task Five:
Query:
SELECT first_name, last_name, meeting.meeting_id, meeting_start, meeting_end
FROM meeting INNER JOIN person_meeting ON meeting.meeting_id=person_meeting.meeting_id
INNER JOIN person ON person.person_id=person_meeting.person_id
AND meeting_start<'2016-12-25 12.00.00';
Task 1,2,4,5 and 5 all run perfectly. if you all need the task prompts, let me know.
Note: I haven't test this yet.
I changed the queries based on our recent interaction.
This is your original
SELECT first_name, last_name, building_name, room.room_id,meeting.meeting_id, meeting_start, meeting_end
FROM meeting, person, person_meeting,room, building
WHERE room.room_id=meeting.room_id
AND meeting.meeting_id=person_meeting.meeting_id
AND person.person_id=person_meeting.person_id
AND room.building_id=building.building_id
AND building_name='Main Street Building';
This is the way I would try to build it
Based on page 2 and 3 in the document, you provided, https://snhu.brightspace.com/d2l/lor/viewer/viewFile.d2lfile/76437/9523,2/, I would do the following:
First, I would obtain information about the building.
SELECT building_id
FROM building
WHERE building_name like '%Main Street Building%';
Note: I am assuming that the building name is correct. However, just in case, I am using the wildcard % before and after the name
Next, I would obtain the information about the room:
SELECT b.building_name, r.room_id
FROM room r
LEFT JOIN building b
ON r.building_id = b.building_id
WHERE b.building_name like '%Main Street Building%';
Following that, I would obtain the information about the meeting:
SELECT b.building_name, r.room_id, m.meeting_id, m.meeting_start, m.meeting_end
FROM room r
LEFT JOIN building b
ON r.building_id = b.building_id
LEFT JOIN meeting m
ON r.room_id = m.room_id
WHERE b.building_name like '%Main Street Building%';
Finally, I would obtain the information of the IDs of people that will be in that meeting and show their names:
SELECT b.building_name, r.room_id, m.meeting_id, m.meeting_start, m.meeting_end, p.first_name, p.last_name
FROM room r
LEFT JOIN building b
ON r.building_id = b.building_id
LEFT JOIN meeting m
ON r.room_id = m.room_id
LEFT JOIN persom_meeting pm
ON m.meeting_id = pm.meeting_id
LEFT JOIN person p
ON pm.person_id = p.person_id
WHERE b.building_name like '%Main Street Building%';
If by any chance, these queries do not work, I would advice that you ensure that the relationships exists between the tables.
This means that there should be a building_id match, a room_id match, a meeting_id match and a person_id match between the tables. Plus, I would check that the building name is spelled correctly since its case-sensitive.
The reason I use LEFT JOINs is so I can display all the information of the previous tables (all the rows) plus the records in which the IDs match the foreign keys IDs. As explained here: http://www.acarlstein.com/?p=4168
Also, in http://www.acarlstein.com/?p=4194, I am showing how a Two Left (Outer)Joins would work.
However, in your case, it is more like a chain that is being build so it doesn't match the diagram but you can perhaps get the idea of what I mean.

my sql output the same data more than one time when i use select statement

I created three tables "student" and "course" and "lecturer" and I inserted data into them.
Now I want to retrieve some data by select.
When I want to show: Subject taken by Kumar
SELECT STUDENT.NAME, COURSE.SUBJECT1, COURSE.SUBJECT2, COURSE.SUBJECT3
FROM STUDENT,COURSE
WHERE STUDENT.COURSE = COURSE.COURSE = 'MLVK'
it repeats the data more than one time.
I hope anyone help me
All the best
Learn to use proper, explicit, standard JOIN syntax.
And, table aliases:
SELECT s.NAME, c.SUBJECT1, c.SUBJECT2, c.SUBJECT3
FROM STUDENT s JOIN
COURSE c
ON s.COURSE = c.COURSE
WHERE c.COURSE = 'MLVK'
If I were going to use these tables to pick subjects taken by Kumar, I would write something like:
SELECT
s.name, c.course, c.subject1, c.subject2, c.subject3
FROM
student as s
LEFT JOIN course as c on c.course = s.course
WHERE
s.no_matrik = '23456'
GROUP BY
s.name, c.course, c.subject1, c.subject2, c.subject3
I think this version makes the intent slightly more clear (pick subject for a particular student, Kumar) than the previous answer (select subjects for any student having course = 'MLVK'). This answer will also return information for Kumar even if he has no course value in the Student table (pre-enrollment?).
First of all I would suggest that to model your data properly in BCNF form, where you should have modelled another table to persist subjects and map the lecturer who take that subject.
Ex: (Subject Table)
SubjectId LECT_ID
---------- ------------
TT234 L123
TT235 L003
and, your Course table would be more of course to subject mapping, like:
CourseName SubjectId
------------- --------------
DTM TT235
DTM TT695
...
then you use query as:
Select sub.SubjectId, l.NAME
From
Student s JOIN
Course c
on c.CourseName = s.COURSE
JOIN Subject sub
on sub.SubjectId = c.SubjectId
JOIN Lecturer l
on l.LECT_ID = sub.Lecturer
Where s.NAME = 'Aminah'
the above query will result as:
SubjectId NAME
--------- ----------
PP563 Ahmad
SS003 Ahmad
PP999 John
as Ahmad happens to be teaching 2 subjects in course DPG. but if you wish to report distinct Lecturers for Aminah, you can change query as:
SELECT NAME FROM Lecturer where LECT_ID
in (
Select l.LET_ID
From
Student s JOIN
Course c
on c.CourseName = s.COURSE
JOIN Subject sub
on sub.SubjectId = c.SubjectId
JOIN Lecturer l
on l.LECT_ID = sub.LECT_ID
Where s.NAME = 'Aminah'
) a

Mysql Joining data from 3 tables

I can't seem to figure out what join I need to do. I have 3 tables which have all the information. I've map out the steps but I'm unsure what to do now, I need to display all the books listed from a specific author.
There is 3 tables I need to use
Author - which contains author_code, fname & lname.
Book - which contains book_code, title, publisher_code, type, price and paperback
Wrote - which contains book_code, author_number and sequence
Here's the code so far, really I know I should use author name but i can't figure it out.
SELECT BOOK_CODE
FROM WROTE
WHERE AUTHOR_NUM = 20
LEFT JOIN AUTHOR
ON WROTE.AUTHOR_NUM = AUTHOR.AUTHOR_NUM;
You need list of book, so start with book table then join it with wrote to get specific author and then join to author to get author data
SELECT BOOK_CODE
FROM BOOK
INNER JOIN WROTE
ON WROTE.BOOK_CODE = BOOK.BOOK_CODE
AND WROTE.AUTHOR_NUM = 20
INNER JOIN AUTHOR
ON AUTHOR.AUTHOR_NUM = WROTE.AUTHOR_NUM
SELECT Book.book_code
FROM Book
LEFT JOIN WROTE ON WROTE.book_code = Book.book_code
LEFT JOIN AUTHOR ON AUTHOR.author_code = WROTE.author_number
WHERE AUTHOR.author_code IN (123,456)

Fetching data from many-to-many relationships

I want to fetch the title from book table and the subject name from subject table for all the books of a certain author
Here is the tables relationships
I have tried to select the title and the subject from the tables but I can't get it to work with the many to many relationship
SELECT book_title,subject_name FROM book,subject WHERE $subject_ID = subject_ID INNER JOIN book_author ON author_ID = '$author_ID'
I thought about making two separate queries, if someone could help me on that I would be really glad.
Try this one:
SELECT book_title, subject_name
FROM Book
INNER JOIN Book_Author ON Book.book_ISBN = Book_Author.book_ISBN
INNER JOIN Author ON Book_Author.author_ID = Author.author_ID
INNER JOIN Subject ON Subject.subject_ID = Book.subject_ID
WHERE author_lastname = [whatever];
And nice job posting the model :)
Edit to match the exact need:
SELECT book_title, subject_name
FROM Book
INNER JOIN Book_Author ON Book.book_ISBN = Book_Author.book_ISBN
INNER JOIN Subject ON Subject.subject_ID = Book.subject_ID
WHERE author_ID = '11';
And by the way, you're having an "Column 'author_ID' in where clause is ambiguous" because this column appears both in Book_Author and Author. That's why you have to prefix it with the table name :)

sql - join 2 tables 10 times

I have 2 tables structured like this:
People
----------
>ID, Name, Surname
Projects
----------
>ID, Assistant#1, Assistant#2, Assistant#3, Assistant#4,
> Assistant#5, Assistant#6, Assistant#7, Assistant#8, Assistant#9,
> Assistant#10, lot of other columns..... (every assistant column
> contains an integer, the people ID)
Now, I want to query my DB and get a single row from Project table (let's suppose row with ID=3) containing all columns of project table and in particular have each assistant replaced with it's correct name and surname.
I've managed to do this (with a lot of joins), but with my little sql experience my code looks very bulky and i'm sure that there's a better way to do this.
Thanks in advance.
SELECT p.Name, p.Surname
FROM People p
CROSS JOIN Project j ON (p.PeopleID = j.Assistant1 OR
p.PeopleID = j.Assistant2 OR
p.PeopleID = j.Assistant3 OR
.. etc)
AND j.ProjectID = 3
Your performance will be awful, but that's the price you pay for having a horribly designed database. The better solution is to map a project and people by the means of a decomposition:
CREATE TABLE proj_people
People_ID INT
Project_ID INT
Your structure is not clear to me. I advice you to create a clutch for projects.
Tables:
Peoples
people_id, people_name, people_surname
Projects
project_id, project_name
Clutch
project_id, people_id
Because you set a number of (possible) assistants at 10, that dictates that you are going to have to write code to accomodate those 10 assistants. This can be done a few ways: (have not tested)
select * from projects proj
left join people p1 on proj.assistant1 = p1.peopleid
left join people p2 on proj.assistant2 = p2.peopleid
left join people p3 on proj.assistant3 = p3.peopleid
left join people p4 on proj.assistant4 = p4.peopleid
left join people p5 on proj.assistant5 = p5.peopleid
left join people p6 on proj.assistant6 = p6.peopleid
left join people p7 on proj.assistant7 = p7.peopleid
left join people p8 on proj.assistant8 = p8.peopleid
left join people p9 on proj.assistant9 = p9.peopleid
left join people p10 on proj.assistant10 = p10.peopleid
otherwise you could do some trickery with
select proj.projectID,
(select * from people where peopleID = proj.assistant1),
(select * from people where peopleID = proj.assistant2),
(select * from people where peopleID = proj.assistant3),
(select * from people where peopleID = proj.assistant4),
(select * from people where peopleID = proj.assistant5),
(select * from people where peopleID = proj.assistant6),
(select * from people where peopleID = proj.assistant7),
(select * from people where peopleID = proj.assistant8),
(select * from people where peopleID = proj.assistant9),
(select * from people where peopleID = proj.assistant10)
from projects proj
If possible, it might be best to re-structure your datatables, and have a single assistant mapped to a single projectID:
PeopleID, Name, Surname
ProjectID, PeopleID
Therefore, you could do just one inner join and you will return a row for each assistant:
select * from projects proj
inner join people p
on p.peopleID = proj.peopleid
where proj.projectID = PROJECTID
Your problem is that you are trying to solve a data presentation issue at the database level and this is rarely a good idea. You should have a table holding projectid and assistantid only, having the combination of both columns as the primary key of the table. This will allow you to join this table to the assistant table and the project table only once and get all the results you need. This will also have the benefit of allowing you to support many more assistants on a project in the future without having to alter your queries to add yet more joins.
In conclusion you should have 3 tables:
Project
Assistant
ProjectAssistant (projectid,assistantid)
you want to restructure your tables. I hate seeing tables with multiple columns for essentially the same thing multiple times. If you restructure to have 3 tables:
Person
PeopleID | Name | Surname
Project
ProjectID | ...other columns except Assistant
Project_Person
ProjectID | PersonID
That way you can assign multiple assistants to the same project without the need for multiple Assistant columns. Then you could use something like this to get the required results:
SELECT proj.ProjectID, pers.Name, pers.Surname
FROM Person pers
INNER JOIN Project_Person pp ON pp.PersonID = pers.PersonID
INNER JOIN Project proj ON proj.ProjectID = pp.ProjectID
This will not return a single row, but that is not how SQL is designed to work.
If you don't want to/can't change the table structure then maybe use a user defined function?
CREATE FUNCTION GET_ASS_NAME (n1 ASS_NO)
RETURNS VARCHAR(50)
DETERMINISTIC
BEGIN
DECLARE fullname VARCHAR(50);
SELECT fullname = CONCAT(NAME, ' ', SURNAME) FROM PEOPLE WHERE ID = n1;
RETURN fullname;
END|
then
select GET_ASS_NAME(1), GET_ASS_NAME(2), GET_ASS_NAME(3), ...
from PROJECTS
where ID = 3
Perhaps a cleaner design is:
People table:
People ID, Name, Surname
ProjectAssistants table:
Project ID, Assistant Person ID
Projects table:
Project ID, lots of other columns (but no Assistant columns)
Then, the SQL becomes something like:
SELECT pr.*, p.*
FROM Projects pr
JOIN ProjectAssistants p_a ON pr.ProjectID = p_a ProjectID
JOIN People p ON p_a.AssistantPersonID = p.PeopleID
WHERE ProjectID = X
Not tested :)
Select * from project pr
left join people pe1 on pe1.peopleid = pr.astint1
left join people pe2 on pe2.peopleid = pr.astint2
left join people pe3 on pe3.peopleid = pr.astint3
left join people pe4 on pe4.peopleid = pr.astint4
left join people pe5 on pe5.peopleid = pr.astint5
left join people pe6 on pe6.peopleid = pr.astint6
left join people pe7 on pe7.peopleid = pr.astint7
left join people pe8 on pe8.peopleid = pr.astint8
left join people pe9 on pe9.peopleid = pr.astint9
left join people pe10 on pe10.peopleid = pr.astint10
where pr.projectid = 3