如何仅显示字段包含多个主题的行

时间:2017-09-12 20:15:31

标签: sql oracle

基本上,我想在同一课程中显示有多个注册用户。当我尝试时,我没有成功,因为这比我预期的更复杂,我有一个不那么简单的场景(我试图应用这里发现的类似案例)。

我需要根据其他表显示这些行,即使用JOIN。

下面的查询仅显示我需要使用此操作处理的三列。如果可能,此查询应该是其他JOIN的一部分,因为我需要显示有关类的其他详细信息。

SELECT eseat.USER_ID, c.COURSE_ID, t.CLASS_ID
FROM
    table_CLASS t                                                                       -- Classes
    LEFT JOIN                                                                           -- This JOIN is necessary to have only the future Classes
    (
        SELECT aa.CLASS_ID, MIN(aa.START_DATE) AS "START", MAX(aa.END_DATE) AS "END"
        FROM table_SEG_CLASS aa                                                         -- Segment x Class
        GROUP BY aa.CLASS_ID
    ) seg ON seg.CLASS_ID = t.CLASS_ID
    LEFT JOIN table_ENROLL_CLASS eseat ON eseat.CLASS_ID = t.CLASS_ID                   -- Enrollment x Class
    LEFT JOIN table_ENROLL_STAT estat ON estat.ENRL_STAT_ID = eseat.ENRL_STAT_ID        -- Enrollment status type
    LEFT JOIN table_COURSE c ON c.COURSE_ID = t.COURSE_ID                               -- Course x Class

WHERE
    1=1
    AND t.CANCELLED = 'N'               -- Only active classes
    AND estat.ENRL_STAT_TYP_ID <> 'C'   -- Not show cancelled enrollment status
    AND SYSDATE <= "END"                -- To show only future classes

贝娄,这些表格的领域。

[table_CLASS]

CLASS_ID | COURSE_ID
T_0001   | C_0001
T_0002   | C_0001
T_0101   | C_0002
T_0201   | C_0003
T_0301   | C_0004
...

[table_SEG_CLASS]

CLASS_ID | START_DATE | END_DATE
T_0001   | 2019-01-01 | 2019-01-02
T_0002   | 2019-02-01 | 2019-02-02 
T_0101   | 2019-03-01 | 2019-03-02
T_0201   | 2019-04-01 | 2019-04-02
T_0301   | 2019-05-01 | 2019-05-02
...

[table_ENROLL_CLASS]

USER_ID | CLASS_ID | ENRL_STAT_ID
00001   | T_0001   | ENROLL
00001   | T_0002   | ENROLL
00001   | T_0101   | ENROLL
00001   | T_0201   | ENROLL
00001   | T_0301   | ENROLL
00002   | T_0001   | ENROLL
00002   | T_0101   | ENROLL
00002   | T_0201   | ENROLL
00002   | T_0301   | ENROLL
...

[table_ENROLL_STAT]

ENRL_STAT_ID | ENRL_STAT_TYP_ID
ENROLL       | E
CANCELLED    | C
WAITLIST     | W
...

[table_COURSE]

COURSE_ID | COURSE_NAME
C_0001    | Course 01
C_0002    | Course 02
C_0003    | Course 03
C_0004    | Course 04
...

输出

USER_ID | COURSE_ID | CLASS_ID
00001   | C_0001    | T_0001
00001   | C_0001    | T_0002
00001   | C_0002    | T_0101
00001   | C_0003    | T_0201
00001   | C_0004    | T_0301
00002   | C_0001    | T_0001
00002   | C_0002    | T_0101
00002   | C_0003    | T_0201
00002   | C_0004    | T_0301

EXPETED OUTPUT

USER_ID | COURSE_ID | CLASS_ID
00001   | C_0001    | T_0001
00001   | C_0001    | T_0002

任何人都可以帮助我吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

有很多方法可以做到这一点。我通常使用EXISTS,但由于你有很多连接,我会坚持使用它。

SELECT eseat.USER_ID, c.COURSE_ID, t.CLASS_ID
FROM
    table_CLASS t                                                                       -- Classes
    LEFT JOIN                                                                           -- This JOIN is necessary to have only the future Classes
    (
        SELECT aa.CLASS_ID, MIN(aa.START_DATE) AS "START", MAX(aa.END_DATE) AS "END"
        FROM table_SEG_CLASS aa                                                         -- Segment x Class
        GROUP BY aa.CLASS_ID
    ) seg ON seg.CLASS_ID = t.CLASS_ID
    LEFT JOIN table_ENROLL_CLASS eseat ON eseat.CLASS_ID = t.CLASS_ID                   -- Enrollment x Class
    LEFT JOIN table_ENROLL_STAT estat ON estat.ENRL_STAT_ID = eseat.ENRL_STAT_ID        -- Enrollment status type
    LEFT JOIN table_COURSE c ON c.COURSE_ID = t.COURSE_ID                               -- Course x Class
-- added this line: user is also enrolled in a different class for this course
    inner join table_enroll_class eseat2 on eseat2.user_id = eseat.user_id 
        and eseat2.class_id in (select class_id from table_class where course_id = t.course_id and class_id <> eseat.class_id)
WHERE
    1=1
    AND t.CANCELLED = 'N'               -- Only active classes
    AND estat.ENRL_STAT_TYP_ID <> 'C'   -- Not show cancelled enrollment status
    AND SYSDATE <= "END"                -- To show only future classes

我认为你可能也希望“eseat”成为一个内部联接,但这只是一个清晰的问题。