Извлеките данные, которых нет в таблице, из четырех связанных таблиц

#mysql #sql #join #left-join

Вопрос:

У меня в базе данных есть четыре таблицы, которые связаны друг с другом.

 document_category(document_category_id, document_category)
document_type(document_type_id, document_category.document_category_id, document_type)
student(student_id, f_name, l_name, ...other_columns)
student_document(id, student.student_id, document_type.document_type_id, file)
 

document_category, document_type, Студенты и студенческий документ

В таблице student_document хранятся загруженные документы. Я хочу, чтобы запрос отображал список документов, которые студент не загружал.

Я пытался

 (SELECT document_type FROM document_category JOIN document_type ON document_category.document_category_id = document_type.document_category_id
) LEFT JOIN(SELECT FILE FROM student_document JOIN student ON student.student_id = student_document.student_id) ON document_type.document_type_id = student_document.document_type_id
 

И я получаю ошибку

 #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'LEFT JOIN(
    SELECT FILE
FROM
    student_document
JOIN student ON stud...' at line 8
 

Я также попробовал это

 SELECT * FROM document_type A LEFT JOIN student_document B ON A.document_type_id = B.document_type_id WHERE B.document_type_id is null
 

что дает мне
результаты
, но я не могу получить данные для конкретного студента.

и последнее, что я пробовал, это

 SELECT student.email, student_document.file, document_type, document_category FROM student, document_type, document_category, student_document WHERE NOT EXISTS(SELECT * FROM student_document WHERE student_id = 'M054/T19' AND document_type_id ='20') AND student.student_id = student_document.student_id AND document_type.document_category_id = document_category.document_category_id
 

Что дает мне Нежелательное, и это не то, чего я хочу.

Комментарии:

1. Назначьте псевдоним подзапросу.

Ответ №1:

 DECLARE @dc TABLE(dc_id Int, ctg VarChar(30));
INSERT INTO @dc VALUES (3,'Admission'),(5,'Payment');
DECLARE @dt TABLE (dt_id Int, dc_id Int, dtp VarChar(30));
INSERT INTO @dt VALUES (27,3, 'Admission Offer'),
(28,3,'Acceptance Letter');
DECLARE @s TABLE(s_id Int, f_name VarChar(30))
INSERT INTO @s VALUES (1, 'Marco'), (2, 'Mike')
DECLARE @sd TABLE (sd_id Int, s_id Int, dt_id Int, [file] VarChar(30))
INSERT INTO @sd VALUES (10,1,27,'File01');

SELECT dc.dc_id, ctg, dt.dt_id, dt.dtp, s.s_id, f_name FROM @dc dc 
JOIN @dt dt ON dc.dc_id = dt.dc_id
CROSS APPLY @s s

-- All expected documents
dc_id   ctg dt_id   dtp s_id    f_name
3   Admission   27  Admission Offer 1   Marco
3   Admission   27  Admission Offer 2   Mike
3   Admission   28  Acceptance Letter   1   Marco
3   Admission   28  Acceptance Letter   2   Mike

-- Provided documents
    SELECT dc.dc_id, ctg, dt.dt_id, dt.dtp, s.s_id, f_name FROM @dc dc 
    JOIN @dt dt ON dc.dc_id = dt.dc_id
    JOIN @sd sd ON sd.dt_id = dt.dt_id
    JOIN @s s ON s.s_id = sd.s_id 

dc_id   ctg dt_id   dtp s_id    f_name
3   Admission   27  Admission Offer 1   Marco

-- Subtracting Set from Set
SELECT dc.dc_id, ctg, dt.dt_id, dt.dtp, s.s_id, f_name FROM @dc dc 
JOIN @dt dt ON dc.dc_id = dt.dc_id
CROSS APPLY @s s
EXCEPT
SELECT dc.dc_id, ctg, dt.dt_id, dt.dtp, s.s_id, f_name FROM @dc dc 
JOIN @dt dt ON dc.dc_id = dt.dc_id
JOIN @sd sd ON sd.dt_id = dt.dt_id
JOIN @s s ON s.s_id = sd.s_id 

dc_id   ctg dt_id   dtp s_id    f_name
3   Admission   27  Admission Offer 2   Mike
3   Admission   28  Acceptance Letter   1   Marco
3   Admission   28  Acceptance Letter   2   Mike
 

Ответ №2:

Этот код работал идеально. Первый запрос, прежде WHERE NOT EXISTS чем получить список всех необходимых документов и список студентов, содержит подробный список документов, которые студент должен загрузить. Вторая часть извлекает список документов, загруженных студентом.

Таким образом, запрос извлекает список необходимых документов, которых нет в списке загруженных документов.

 SELECT sp.student_id, do.document_type_id, do.document_type 
FROM student_profile sp 
CROSS JOIN document_type do 
WHERE NOT EXISTS (SELECT sd.student_id, sd.document_type_id, d.document_type FROM student_document sd 
INNER JOIN document_type d ON sd.document_type_id = d.document_type_id 
WHERE do.document_type_id = sd.document_type_id 
AND sp.student_id = sd.student_id );
 

Комментарии:

1. Пожалуйста, добавьте некоторые пояснения к вашему ответу, чтобы другие могли извлечь из него уроки