多个SQL连接难以查询

时间:2015-03-25 07:16:51

标签: mysql sql sql-server join inner-join

我有一个奇怪的架构但是当它被设计时,它在当时似乎是一个好主意。我有一个lesson_objects,它有外键链接到词汇表,视频和测验表。

词汇表:

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

只有我的查询不返回任何行,理想情况下,它应该为包含SOME空列的每个记录转换多行。例如。如果它不是词汇表,则测验和视频的列将为空。

我的尝试非常糟糕,但这里有一个是为了指导:

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

任何帮助/意见将不胜感激。感谢。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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子句中包含大量条件。