JOIN MySQL Tables - mysql

I have following tables format:
members
mem_id | mem_name
------------------
1 A
2 B
3 C
project_members
fk_mem_id | meb_parent_id
-------------------------
1 0
2 1
3 2
and I require result like:
mem_id | child| parent
--------------------------
1 A NULL
2 B A
3 C B
I tried but fail.. any idea....?
SELECT pm.*, m1.meb_name as child, m2.meb_name as parent
FROM members m1
LEFT JOIN members m2
ON m1.meb_parent_id = m2.meb_id

SELECT project_members.fk_mem_id,
a.mem_name AS child,
b.mem_name AS parent
FROM project_members
INNER JOIN members a
ON project_members.fk_mem_id = a.mem_id
LEFT JOIN members b
ON project_members.meb_parent_id = b.mem_id

Related

MySQL one to many get the no matching record

Im not good at explaining things so please bear with me.. Here's what I'm trying to do. I want to get the result of rows with no matching record to the table(tbl_personnel_documents) if I'm looking for the documents with a "YES" priority and based on their position.
Here's the structure of the table for employee:
tbl_personnel_info
id name position_id
1 John 1
2 Sharyn 2
3 Stacie 4
4 Kevin 3
5 Cristine 3
Table for Position:
tbl_position
id position_name
1 IT Manager
2 Accounting Staff
3 IT Staff
4 H.R Manager
5 Admin Staff
Table for personnel documents:
tbl_personnel_documents
id personnel_id document_id document_num
1 1 3 111-222-333-444
2 1 4 AB-CC-DD
3 2 1 CC-BB-DD
4 4 2 1-2-3-4-5
5 3 4 C1-D2-X1-D2-G3
Table for documents name
tbl_documents
id document_name priority
1 Passport YES
2 ROPC NO
3 US Visa YES
4 AUS Visa YES
Table for document priority based on their position
tbl_priority_docs_per_position
id position_id document_id
1 1 1
2 1 3
3 1 4
In this case, John's position is an IT Manager which have no record of passport in the table(tbl_personnel_documents). And since the document Passport is a priority document for IT Manager but it is missing, it must display the result.
Im currently stuck in here.. I can't get the desired result.. Here's my code:
SELECT td.document_name
FROM tbl_personnel_info AS tpi
LEFT JOIN tbl_position AS tp
ON tp.id = tpi.position_id
LEFT JOIN tbl_personnel_documents AS tpd
ON tpi.id = tpd.personnel_id
LEFT JOIN tbl_documents AS td
ON td.id = tpd.document_id
LEFT JOIN tbl_priority_docs_per_position AS tpriority
ON tpriority.position_id = tpi.position_id AND tpriority.document_id = tpd.document_id
WHERE td.priority = 'YES'
AND tpi.id = 1 -- John's ID
AND tpriority.document_id IS NULL
Please help.. Thank you
Update: I manage to partially get the result with this code:
SELECT td.document_name
FROM tbl_personnel_info AS tpi
LEFT JOIN tbl_position AS tp
ON tp.id = tpi.position_id
LEFT JOIN tbl_personnel_documents AS tpd
ON tpi.id = tpd.personnel_id
LEFT JOIN tbl_documents AS td
ON td.priority = 'YES'
LEFT JOIN tbl_priority_docs_per_position AS tpriority
ON tpriority.position_id = tpi.position_id AND tpriority.document_id = tpd.document_id
WHERE tpi.id = 1 -- John's ID
AND tpriority.document_id IS NULL
GROUP BY td.id
Now my problem is whenever I change the position_id of tbl_priority_docs_per_position, I still get the same result.
When you use a left join you must be very careful how you reference that table in the where clause or you might override the join. Here however I believe it is the sequence of joins:
SELECT
*
FROM tbl_personnel_info AS tpi
INNER JOIN tbl_position AS tp ON tp.id = tpi.position_id
INNER JOIN tbl_priority_docs_per_position AS tpriority ON tpriority.position_id = tpi.position_id
LEFT JOIN tbl_personnel_documents AS tpd ON tpi.id = tpd.personnel_id
AND tpriority.document_id = tpd.document_id
LEFT JOIN tbl_documents AS td ON td.id = tpd.document_id
WHERE tpi.id = 1 -- John's ID
AND td.priority IS NULL
;
Demo
| id | name | position_id | id | position_name | id | position_id | document_id | id | personnel_id | document_id | document_num | id | document_name | priority |
|----|------|-------------|----|---------------|----|-------------|-------------|--------|--------------|-------------|--------------|--------|---------------|----------|
| 1 | John | 1 | 1 | IT Manager | 1 | 1 | 1 | (null) | (null) | (null) | (null) | (null) | (null) | (null) |

How to select rows, which have all or none corresponding values in another table?

I'm not sure I phrased the question correctly, so feel free to correct me. Here are the tables with their data:
product category category_product
------- -------- ----------------
id_product id_category active id_category id_product
1 1 1 1 1
2 2 1 2 1
3 3 0 1 2
4 0 2 2
3 2
3 3
4 3
I need to select only those products, which have all categories as inactive.
For example:
Product 1 is good, since it belongs to active categories (1, 2).
Product 2 is good, since it has at least one active category (1, 2; 3 - inactive)
Product 3 must be selected, since all its categories are inactive (3, 4).
I have the following query, which is obviously incorrect, since it selects both products: 2 and 3:
SELECT p.id_product
FROM product p
JOIN category_product cp
ON p.id_product = cp.id_product
JOIN category c
ON c.id_category = cp.id_category
WHERE
c.active = 0;
Here is the SQL Fiddle: http://sqlfiddle.com/#!2/909dd/2/0
How can I solve this?
This way you can select product without active category.
SELECT p.id_product
FROM product p
WHERE NOT EXISTS
(SELECT * FROM
category_product cp
INNER JOIN category c ON c.id_category = cp.id_category
WHERE p.id_product = cp.id_product AND c.active = 1);
SQL Fiddle
Consider the following:
SELECT p.*
, COUNT(*)
, SUM(c.active = 1) active
, SUM(c.active = 0) inactive
FROM product p
JOIN category_product cp
ON cp.id_product = p.id_product
JOIN category c
ON c.id_category = cp.id_category
GROUP
BY p.id_product;
+------------+----------+--------+----------+
| id_product | COUNT(*) | active | inactive |
+------------+----------+--------+----------+
| 1 | 2 | 2 | 0 |
| 2 | 3 | 2 | 1 |
| 3 | 2 | 0 | 2 |
+------------+----------+--------+----------+
http://sqlfiddle.com/#!2/909dd/55
The last part of this problem has been left as an exercise for the reader
This is what i get while trying...apologies if anything is wrong
set #count:=0;
select a.id_product,a.times from
(SELECT count(p.id_product)times, p.id_product, c.active,
if(c.active!=0, #count:=#count+1, #count:=0) x
From category_product cp
join product p
on (p.id_product = cp.id_product)
join category c
on(c.id_category = cp.id_category )
group by id_product )a
where a.x=0;

How to write SQL below in order to display all details

I don't know if I am doing the below method correctly when using sql but here it goes.
I want to display all exam details (exams details (Also know as Session), questions in exam, answers, penalty, images, videos etc) But the way I am trying to do it is one big query but it is not working as no rows are being displayed.
Below are what I want to display for one exam (and only one exam):
Exam Details
All questions in Exam
All Answers to each question and marks each answer worth
Penalty (see if enabled or not)
Penalty marks for incorrect answers
Images in question
Videos in questions
Audio in questions
Module Details
Student
Below show the fields each section above require from database:
Exam Details
SessionId, SessionName, SessionDuration, TotalMarks, SessionWeight
All questions in Exam
QuestionId, QuestionNo, QuestionContent, NoofAnswers, QuestionMarks, OptionId, OptionType, ReplyId, ReplyType
All Answers to each question and marks each answer worth
AnswerId, Answer, AnswerMarks
Penalty (see if enabled or not)
PenaltyEnabled
Penalty answers
PenaltyAnswerId, PenaltyAnswer, PenaltyMarks
Images in question
ImageId, ImageFile
Videos in questions
VideoId VideoFile
Audio in questions
AudioId, AudioFile
Module Details
ModuleId, ModuleNo, ModuleName
Student
StudentId
My question is how should the SQL code be written in order for all these data to be shown? Do I just need one big query or a lot of little queries? My attempt is at bottom of question but below is the database tables which shows details dealing with one exam and all its details.
TABLES:
Student
StudentId (PK) StudentForename StudentSurname
1 James Parker
Student_Session
SessionId (FK) StudentId (FK)
1 1
Session
SessionId (PK) SessionName SessionDuration TotalMarks SessionWeight ModuleId (FK)
1 AAA 01:00:00 30 20 1
Module
ModuleId (PK) ModuleNo ModuleName
1 CHI2513 ICT
Question
SessionId FK) QuestionId (PK) QuestionNo QuestionContent NoofAnswers QuestionMarks OptionId (FK) ReplyId (FK)
1 4 1 Question 1 1 5 1 1
1 5 2 Question 2 1 3 2 1
1 6 3 Question 3 2 6 2 2
1 7 4 Question 4 3 7 5 2
1 8 5 Question 5 1 9 5 1
Answer:
AnswerId (PK) Answer QuestionId (FK)
1 A 4
2 C 5
3 A 6
4 B 6
5 B 7
6 D 7
7 E 7
8 G 8
Individual Answer
IndividualId (PK) AnswerId (FK) AnswerMarks
1 1 3
2 2 5
3 3 3
4 4 3
5 5 2
6 6 2
7 7 3
8 8 9
Penalty
PenaltyId(PK) SessionId (FK) PenaltyEnalbed
1 1 1
PenaltyMarks
PenaltyAnswerId (PK) PenaltyAnswer PenaltyMarks QuestionId (FK)
1 B 1 4
2 C 1 4
3 A 1 5
4 B 1 5
5 D 1 5
6 C 2 6
7 D 2 6
8 A 1 7
9 C 1 7
10 F 1 7
11 G 1 7
12 A 0 8
13 B 0 8
14 C 1 8
15 D 1 8
16 E 1 8
17 F 0 8
Reply
ReplyId (PK) ReplyType
1 Single
2 Multiple
Option_Table
OptionId (PK) OptionType
1 A-C
2 A-D
3 A-E
4 A-F
5 A-G
Image
ImageId (PK) ImageFile
1 ImageFile/Tulips.png
2 ImageFile/Daisys.png
Video
VideoId (PK) VideoFile
1 VideoFile/Speech.png
Audio
AudioId (PK) AudioFile
1 AudioFile/Song.png
Image_Question
ImageQuestionId (PK) ImageId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 2
Video_Question
VideoQuestionId (PK) VideoId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 4
Audio_Question
AudioQuestionId (PK) AudioId (FK) SessionId (FK) QuestionNo (FK)
1 1 1 5
Below was my failed attempt:
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
INNER JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionNo
INNER JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionNo
INNER JOIN Video v
ON vq.VideoId = v.VideoId
WHERE s.SessionId = 1
ORDER BY q.QuestionId
UPDATE:
Will the code below be able to insert QuestionId into Image_Question Table after questions submitted: (This is something I found on SO but updated to my table design)
ImageQuestionToken
{
ImageToken (PK auto)
SessionId
}
Image{
ImageId
ImageFile
}
Image_Question
{
Image_QuestionId
ImageId FK references Image(ImageId)
QuestionId FK references Question(QuestionId)
}
Question
{
QuestionId (PK Auto)
QuestionNo
QuestionContent
....
}
TempImage
{
ImageToken FK references ImageQuestionToken(ImageToken)
ImageFile
}
And the logic like so:
User requests question form. Server sets token and includes in response to user.
User uploads picture including token. Image is stored in temporary table.
Step 2 repeated n times.
If user submits question with token value, an entry is placed in the questions table and an id is assigned. All images in the TempImage table that share the token get inserted to the image table with the now known QuestionId. The ImageQuestionToken entry is then deleted and cascade deletes the temp images in TempImage.
Else user doesn't submit question then files are deleted and ImageQuestionToken entry deleted.
While I am not 100% sure of the exact result that you want. Based on your existing query the issue is that you are using INNER JOIN on some of the tables when you should be using LEFT JOIN.
In your existing query you are using the following:
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
INNER JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionNo
INNER JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionNo
INNER JOIN Video v
ON vq.VideoId = v.VideoId
The problem is that the INNER JOIN is checking for matching records on all fields but you might not have a record that exists in the image, audio or video tables so it is not returning anything.
Based on your details your query should be similar to this:
select st.studentid,
s.sessionid,
s.sessionname,
s.sessionduration,
s.totalmarks,
s.sessionweight,
q.questionid,
q.questionno,
q.questioncontent,
q.noofanswers,
q.questionmarks,
q.optionid,
ot.optiontype,
q.replyid,
r.replytype,
a.answerid,
a.answer,
ia.answermarks,
p.penaltyenabled,
pm.penaltyanswerid,
pm.penaltyanswer,
pm.penaltymarks,
i.imageid,
i.imagefile,
v.videoid,
v.videofile,
ad.audioid,
ad.audiofile,
m.moduleid,
m.moduleno,
m.modulename
from Student st
inner join Student_Session ss
on st.studentid = ss.studentid
inner join session s
on ss.sessionid = s.sessionid
inner join question q
on s.sessionid = q.sessionid
inner join answer a
on q.questionid = a.questionid
inner join Individual_Answer ia
on a.answerid = ia.answerid
left join Option_Table ot
on q.optionid = ot.optionid
left join reply r
on q.replyid = r.replyid
left join module m
on s.moduleid = m.moduleid
left join Penalty p
on s.sessionid = p.sessionid
left join penalty_marks pm
on q.questionid = pm.questionid
left join image_question iq -- note I am joining on both session and question
on s.sessionid = iq.sessionid
and q.questionid = iq.questionno
left join image i -- this should be a left join not inner join
on iq.imageid = i.imageid
left join video_question vq -- note I am joining on both session and question
on s.sessionid = vq.sessionid
and q.questionid = vq.questionno
left join video v -- this should be a left join not inner join
on vq.videoid = v.videoid
left join audio_question aq -- note I am joining on both session and question
on s.sessionid = aq.sessionid
and q.questionid = aq.questionno
left join audio ad -- this should be a left join not inner join
on aq.audioid = ad.audioid
where s.SessionId = 1
order by q.QuestionId
See SQL Fiddle with Demo.
This is returning all of the data that you have requested above. Sample:
| STUDENTID | SESSIONID | SESSIONNAME | SESSIONDURATION | TOTALMARKS | SESSIONWEIGHT | QUESTIONID | QUESTIONNO | QUESTIONCONTENT | NOOFANSWERS | QUESTIONMARKS | OPTIONID | OPTIONTYPE | REPLYID | REPLYTYPE | ANSWERID | ANSWER | ANSWERMARKS | PENALTYENABLED | PENALTYANSWERID | PENALTYANSWER | PENALTYMARKS | IMAGEID | IMAGEFILE | VIDEOID | VIDEOFILE | AUDIOID | AUDIOFILE | MODULEID | MODULENO | MODULENAME |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 4 | 1 | Question 1 | 1 | 5 | 1 | A-C | 1 | Single | 1 | A | 3 | 1 | 1 | B | 1 | (null) | (null) | 1 | VideoFile/Speech.png | (null) | (null) | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 4 | 1 | Question 1 | 1 | 5 | 1 | A-C | 1 | Single | 1 | A | 3 | 1 | 2 | C | 1 | (null) | (null) | 1 | VideoFile/Speech.png | (null) | (null) | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 3 | A | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 5 | D | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
| 1 | 1 | AAA | 01:00:00 | 30 | 20 | 5 | 2 | Question 2 | 1 | 3 | 2 | A-D | 1 | Single | 2 | C | 5 | 1 | 4 | B | 1 | (null) | (null) | (null) | (null) | 1 | AudioFile/Song.png | 1 | CHI2513 | ICT |
There's a problem with your foreign keys in these tables: Image_Question, Audio_Question, and Video_Question.
You are using the column QuestionNo which is not indexed by the table Question.
I would suggest replacing the columns as QuestionId instead and used their values.
Image_Question
ImageQuestionId (PK) ImageId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 2
Video_Question
VideoQuestionId (PK) VideoId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 4
Audio_Question
AudioQuestionId (PK) AudioId (FK) SessionId (FK) QuestionNo(FK)
1 1 1 5
and your statement should look like this:
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
LEFT JOIN Image_Question iq
ON q.QuestionNo= iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionNo= aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionNo= vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
WHERE s.SessionId = 1
ORDER BY q.QuestionId
update:
You can use the column QuestionNo afterall, you could just add index so you don't have to overhaul your codes. hehehe
i suggest you add this:
ALTER TABLE `your_schema`.`Question`
ADD INDEX `your_idx` (`QuestionNo` ASC);
and instead of these:
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionId -- from iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionId = aq.QuestionId -- from aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionId = vq.QuestionId -- from vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
you use these:
LEFT JOIN Image_Question iq
ON q.QuestionNo= iq.QuestionNo
LEFT JOIN Image i
ON iq.ImageId = i.ImageId
LEFT JOIN Audio_Question aq
ON q.QuestionNo= aq.QuestionNo
LEFT JOIN Audio au
ON aq.AudioId = au.AudioId
LEFT JOIN Video_Question vq
ON q.QuestionNo= vq.QuestionNo
LEFT JOIN Video v
ON vq.VideoId = v.VideoId
The key problem: often, no rows will be returned using an inner join off of an outer joined table
I have subqueried, using microsoft SQL syntax. Hope it helps. See my warnings at the bottom, and ignore the create procedure statement if you like and instead just declare and set the #SessionID to 1 at the top.
create procedure GetStuff(
#SessionID as integer
) as
declare #StudentID int -- you may need to use a different data type
select #StudentID = StudentID from Student_Session where SessionID = #SessionID
-- now we can at least remove the sessions table from the join list.
SELECT s.SessionId,
SessionName,
SessionDuration,
TotalMarks,
SessionWeight,
q.QuestionId,
q.QuestionNo,
QuestionContent,
QuestionMarks,
q.OptionId,
OptionType,
q.ReplyId,
ReplyType,
a.AnswerId,
Answer,
NoofAnswers,
AnswerMarks,
PenaltyEnabled,
PenaltyAnswerId,
PenaltyAnswer,
PenaltyMarks,
i.ImageId,
au.AudioId,
v.VideoId,
ImageFile,
AudioFile,
VideoFile,
s.ModuleId,
ModuleNo,
ModuleName,
ss.StudentId
FROM Student st
INNER JOIN Student_Session ss
ON st.StudentId = ss.StudentId
INNER JOIN Session s
ON ss.SessionId = s.SessionId
INNER JOIN Question q
ON s.SessionId = q.SessionId
INNER JOIN Answer a
ON q.QuestionId = a.AnswerId
INNER JOIN Individual_Answer ia
ON a.AnswerId = ia.AnswerId
LEFT outer JOIN Module m
ON s.ModuleId = m.ModuleId
LEFT outer JOIN Penalty p
ON q.SessionId = p.SessionId
LEFT outer JOIN Option_Table o
ON q.OptionId = o.OptionId
LEFT outer JOIN Reply r
ON q.ReplyId = r.ReplyId
LEFT outer JOIN Penalty_Marks pm
ON q.QuestionId = pm.QuestionId
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
LEFT outer JOIN (select c3.ImageID, c3.ImageFile from Image_Question as a1 inner join Images as b1 on a1.QuestionNo = b1.QuestionNo inner join Image as c1 on a1.ImageID = c1.ImageID)
ON q.QuestionID = iq.QuestionID
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
LEFT outer JOIN (select b2.AudioID, b2.AudioFile from Audio_Question as a2 inner join Audio as b2 on a2.AudioID = b2.AudioID) as aq
ON q.QuestionId = aq.QuestionNo
-- you can't inner join off of an outer joined table, or you'll get no rows for the entire query. I've nested the query, which is bad practice but... practical for getting this monster of a query working.
left outer join (select b3.VideoID, b3.VideoFile from Video_Question as a3 inner join Video as b3 on a3.QuestionID = b3.QuestionID) as vq
WHERE
st.StudentID = #StudentID
and
s.SessionId = #SessionID
ORDER BY q.QuestionId
go
Warnings:
You will really want to break this down to seperate peices for displaying in your client application. For instance, you need a master/detail display for Exams and ExamDetails, otherwise you would have to suppress repeating values in the output shown to the user.
For instance, your output would look like this, conceptually:
<Exam Detail Fields> <Exam Detail Fields>
first one unique What is the color of your DOG?
repeat What is the color of your CAT?
repeat What is the color of your CAR?
repeat What is the color of your HAT?
Note the repetitive values on the left that you would have to suppress.
Well , Try it in small shifts : what I mean is:- Execute the query part by part
remove some joins at first (remove most of them ),and add them one by one ,I do the same for my huge queries to track where is the actual problem, or which conditions are making the main differences for getting the resulted rows. just an Idea. Cheers!
And i think
LEFT JOIN Image_Question iq
ON q.QuestionId = iq.QuestionNo
will give you null values
As q.QuestionId starts form 4 and iq.QuestionNo is 2
INNER JOIN Image i
ON iq.ImageId = i.ImageId
And all the values in Iq fields resulted from Left outer joins are null.So any Inner Join on them is Sure to give you null results.

mysql join show all records in left table with a flag for matching records in right table

I need a help from mySQL Join tables which should list all users in 'Table A' and also should show flag by matching records in 'Table B'
Table A (users)
=====================
id | name
=====================
1 | aaa
2 | bbb
3 | ccc
4 | ddd
5 | eee
Table B (users_likes)
=====================
like_by | like_to
=====================
1 | 2
1 | 3
2 | 3
4 | 1
5 | 1
if user 'aaa'(id:1) login to the system and performs a search to list all users except his details so the results will be
2 | bbb
3 | ccc
4 | ddd
5 | eee
also he needs to see a flag when listing which shows his 'like_by'
eg:
2 | bbb | (flag:TRUE)
3 | ccc | (flag:TRUE)
4 | ddd | flag:false)
5 | eee | (flag:false)
an easy solution for your problem is to use UNION and few SubQuery(although other solution may exist other than this)
SQLFiddle Demo
SELECT DISTINCT b.id, b.name,'TRUE' AS FLAG
FROM users_likes a
INNER JOIN users b
on a.like_to = b.id
WHERE like_by = 1
UNION
SELECT DISTINCT id, name,'FALSE' AS FLAG
FROM users
WHERE ID NOT IN
(
SELECT DISTINCT b.id
FROM users_likes a
INNER JOIN users b
on a.like_to = b.id
WHERE like_by = 1
)
AND id <> 1
or without using UNION and much simplier solution is the one below.
SQLFiddle Demo
SELECT a.id,
a.name,
IF(COALESCE(b.like_by, -1) = 1, 'TRUE', 'FALSE') AS `Flag`
FROM users a
LEFT JOIN users_Likes b
ON a.id = b.like_to
WHERE a.ID <> 1
GROUP BY a.id
Try this query
select
B.like_to,
BNames.name,
case when B.like_by = 1 then True else False end
from Table_A A
left outer join Table_B B on A.id = B.like_by
left outer join Table_A BNames on B.like_to = BNames.id
where B.like_to <> 1
hope it helps.
I think this is what you're after:
SELECT a.id,a.name,b.like_by IS NOT NULL
FROM users a
LEFT JOIN users_likes b ON (a.id = b.like_to)
GROUP BY a.id
This will give all items of 'a' with 1 where there is a like_to to that a and 0 where there isn't.
(You can add WHERE a.id != 1 to exclude user 1).
Edit:
Changing the third column to be true false based on user 1's likes. I originally thought it was any like.
SELECT a.id,a.username,b.like_by IS NOT NULL
FROM users a
LEFT JOIN user_likes b ON (a.id = b.like_to AND b.like_by = 1)
WHERE a.id != 1
GROUP BY a.id
http://sqlfiddle.com/#!2/ea34d/10

Joining two tables with MySQL for aggregation?

I need to join tables to do aggregation. I suck at that. Here's my scenario:
CATEGORIES
CatID | CategoryName | Parent
1 | Cars | NULL
2 | Electronics | NULL
3 | DVD | 2
4 | Blu_ray | 2
5 | Shoes | NULL
So basically, topmost elements don't have parents. Then I have
PRODUCTS
ProdID | Prod Name | CatID
1 | DVD Player 1 | 3
2 | Blu-Ray Player | 3
3 | Nike | 5
4 | DVD Player 2 | 3
I want to end up with...
CATEGORIES
CatID | CategoryName | Parent | totalProds
1 | Cars | NULL | 0
2 | Electronics | NULL | 0
3 | DVD | 2 | 2
4 | Blu_ray | 2 | 1
5 | Shoes | NULL | 1
Any ideas?
Aren't you just asking for the total number of products per category?
SELECT CatID, CategoryName, Parent, COUNT(*) totalProds
FROM categories c
INNER JOIN products p ON p.CatID = c.CatID
GROUP BY CatId
See below query
SELECT
c.`CatID`,
c.`CategoryName`,
c.`Parent`,
COALESCE(COUNT(DISTINCT p.`ProdID`),0) AS totalProds
FROM `CATEGORIES` c
LEFT JOIN `PRODUCTS` p
ON p.`CatID` = c.`CatID`
ORDER BY c.`CatID`
LEFT JOIN to return a row for every category. COALESCE to just make sure a 0 is returned if appropriate.
Assuming you have a limited number of category levels, you can union each level at a time. Here's for 4 levels:
SELECT c1.CatID, c1.CategoryName, c1.Parent, COUNT(1) totalProds
FROM products p
INNER JOIN categories c1 ON c1.CatID = p.CatID
GROUP BY c1.CatID, c1.CategoryName, c1.Parent
UNION
SELECT c2.CatID, c2.CategoryName, c2.Parent, COUNT(1)
FROM products p
INNER JOIN categories c1 ON c1.CatID = p.CatID
INNER JOIN categories c2 ON c2.CatID = c1.Parent
GROUP BY c2.CatID, c2.CategoryName, c2.Parent
UNION
SELECT c3.CatID, c3.CategoryName, c3.Parent, COUNT(1)
FROM products p
INNER JOIN categories c1 ON c1.CatID = p.CatID
INNER JOIN categories c2 ON c2.CatID = c1.Parent
INNER JOIN categories c3 ON c3.CatID = c2.Parent
GROUP BY c3.CatID, c3.CategoryName, c3.Parent
UNION
SELECT c4.CatID, c4.CategoryName, c4.Parent, COUNT(1)
FROM products p
INNER JOIN categories c1 ON c1.CatID = p.CatID
INNER JOIN categories c2 ON c2.CatID = c1.Parent
INNER JOIN categories c3 ON c3.CatID = c2.Parent
INNER JOIN categories c4 ON c4.CatID = c3.Parent
GROUP BY c4.CatID, c4.CategoryName, c4.Parent
Hope you get the idea...