2015-03-25 78 views
1

我有一個奇怪的模式,但是當它被設計時,它似乎是一個好主意。我有一個表,lesson_objects,它有外鍵鏈接到詞彙,視頻和測驗表。多個SQL加入困難查詢

詞彙表:

CREATE TABLE `se_vocab` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `vocab_word` VARCHAR(255) NOT NULL, 
    `vocab_audio` INT(10) NULL DEFAULT '0', 
    `vocab_image` INT(10) NULL DEFAULT '0', 
    PRIMARY KEY (`id`) 
) 

視頻表:

CREATE TABLE `se_video` (
    `id` INT(10) NOT NULL AUTO_INCREMENT, 
    `video_name` VARCHAR(255) NOT NULL, 
    `video_description` MEDIUMTEXT NOT NULL, 
    `video_file_name` VARCHAR(50) NULL DEFAULT NULL, 
    `video_url` VARCHAR(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) 

測驗表:

CREATE TABLE `se_quizzes` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `quiz_name` VARCHAR(80) NOT NULL, 
    `quiz_description` TINYTEXT NULL, 
    PRIMARY KEY (`id`) 
) 

教訓的對象(包括先前的表的外鍵)

CREATE TABLE `se_lesson_org` (
    `id` INT(10) NOT NULL AUTO_INCREMENT, 
    `lesson_id` INT(10) NOT NULL, 
    `section_object_type` ENUM('video','vocabulary','quiz') NOT NULL, 
    `section_object_id` INT(10) NOT NULL, 
    PRIMARY KEY (`id`) 
) 

我試圖創建一個從lesson_objects返回所有記錄的查詢,但也包括在該記錄類型的列中的數據(詞彙等)

例如: enter image description here

只有我的查詢不返回行,而最好應該把多行包含若干空列的每個記錄。例如。如果它不是詞彙表,測驗和視頻的列將爲空。

我的企圖是非常糟糕的,但這裏是一個指導的緣故:

SELECT 
    lo.id, lo.section_object_type, lo.section_object_id, 
    vo.id, vo.vocab_text, vo.vocab_image, vo.vocab_audio 
    vi.id, vi.video_name, vi.video_url, 
    q.id, q.quiz_name 
    FROM se_lesson_org lo, se_vocab vo, se_video vi, se_quizzes q 
    WHERE lo.section_object_id = vo.id 
    OR lo.section_object_id = vi.id 
    OR lo.section_object_id = q.id 

任何幫助/意見將不勝感激。謝謝。

+0

顯示樣本數據或創建一個sqlfiddle – Jens 2015-03-25 07:18:59

+1

請張貼預期的結果格式。 – 2015-03-25 07:19:30

+0

MySQL或/和SQL Server?不要標記不涉及的產品! – jarlh 2015-03-25 07:44:02

回答

2

使用LEFT JOIN返回se_lesson_org的所有行。此外,添加一個JOIN條件以匹配特定section_object_type

SELECT 
    lo.*, 
    vo.*, 
    vi.*, 
    q.* 
FROM se_lesson_org lo 
LEFT JOIN se_vocab vo 
    ON vo.id = lo.section_object_id 
    AND lo.section_object_type = 'vocabulary' 
LEFT JOIN se_video vi 
    ON vi.id = lo.section_object_id 
    AND lo.section_object_type = 'video' 
LEFT JOIN se_quizzes q 
    ON q.id = lo.section_object_id 
    AND lo.section_object_type = 'quiz' 

注:避免使用舊式JOIN語法。閱讀Aaron Bertrand的article

+0

令人驚歎的東西。完美的作品。我會看看那篇文章。謝謝! – markbratanov 2015-03-25 07:30:37

+0

沒問題,很高興我能幫上忙。 – 2015-03-25 07:31:24

+1

不錯的文章,@wewesthemenace。當他談論'* =,= *'時,他的意思是什麼?可能是一個愚蠢的問題,但我沒有看到他所查詢的查詢中...... – 2015-03-25 07:34:43

1

聽起來像你正在尋找每個這些表上的LEFT JOIN。這樣,如果外鍵是有效的,你將顯示值,如果它是無效的,你只會得到NULL的相關列。

SELECT 
    lo.id, lo.section_object_type, lo.section_object_id, 
    vo.id, vo.vocab_text, vo.vocab_image, vo.vocab_audio 
    vi.id, vi.video_name, vi.video_url, 
    q.id, q.quiz_name 
    FROM se_lesson_org lo 
    LEFT JOIN se_vocab vo ON vo.id = lo.section_object_id 
     AND lo.section_object_type = 'vocabulary' 
    LEFT JOIN se_video vi ON vi.id = lo.section_object_id 
     AND lo.section_object_type = 'video' 
    LEFT JOIN se_quizzes q ON q.id = lo.section_object_id 
     AND lo.section_object_type = 'quiz' 

通知該語法也如何清楚如何每個表被連接到查詢的其餘部分,而不是在端部的WHERE子句中具有的條件下整個的混亂。

+0

偉大的作品,並感謝您的解釋。我想這就是爲什麼我在這個學期學習SQL類。 – markbratanov 2015-03-25 07:31:48