Students who have taken the test for every course in their degree





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I've been trying to do a "Not exist" approach to isolate the answer, but I think I've gone a bit too deep. I'm limited to essentially only using like really basic stuff for my intro to database class. So, basically only INNER JOIN, UNION, and CASE and maybe a few other stuff, but probably best assume like the bare bones stuff. We're not allowed to use coalesce yet.










share|improve this question

























  • how did stu002 manage to take an exam this isnt in a course?

    – Caius Jard
    Oct 29 '18 at 21:38











  • since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

    – Preli
    Oct 29 '18 at 21:45


















1















I've been trying to do a "Not exist" approach to isolate the answer, but I think I've gone a bit too deep. I'm limited to essentially only using like really basic stuff for my intro to database class. So, basically only INNER JOIN, UNION, and CASE and maybe a few other stuff, but probably best assume like the bare bones stuff. We're not allowed to use coalesce yet.










share|improve this question

























  • how did stu002 manage to take an exam this isnt in a course?

    – Caius Jard
    Oct 29 '18 at 21:38











  • since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

    – Preli
    Oct 29 '18 at 21:45














1












1








1








I've been trying to do a "Not exist" approach to isolate the answer, but I think I've gone a bit too deep. I'm limited to essentially only using like really basic stuff for my intro to database class. So, basically only INNER JOIN, UNION, and CASE and maybe a few other stuff, but probably best assume like the bare bones stuff. We're not allowed to use coalesce yet.










share|improve this question
















I've been trying to do a "Not exist" approach to isolate the answer, but I think I've gone a bit too deep. I'm limited to essentially only using like really basic stuff for my intro to database class. So, basically only INNER JOIN, UNION, and CASE and maybe a few other stuff, but probably best assume like the bare bones stuff. We're not allowed to use coalesce yet.







sql postgresql






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 15:07







Anon Li

















asked Oct 29 '18 at 20:33









Anon LiAnon Li

457




457













  • how did stu002 manage to take an exam this isnt in a course?

    – Caius Jard
    Oct 29 '18 at 21:38











  • since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

    – Preli
    Oct 29 '18 at 21:45



















  • how did stu002 manage to take an exam this isnt in a course?

    – Caius Jard
    Oct 29 '18 at 21:38











  • since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

    – Preli
    Oct 29 '18 at 21:45

















how did stu002 manage to take an exam this isnt in a course?

– Caius Jard
Oct 29 '18 at 21:38





how did stu002 manage to take an exam this isnt in a course?

– Caius Jard
Oct 29 '18 at 21:38













since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

– Preli
Oct 29 '18 at 21:45





since we don't see from the question if there is a course table or not "Calc C" might exist, but not be mandatory for any specific program?

– Preli
Oct 29 '18 at 21:45












3 Answers
3






active

oldest

votes


















0














Not sure if this is possible with just INNER JOIN, UNION, and CASE -> but I found a solution with an outer join (still quite simple).



Lets try to solve this in two steps.



1) Lets see which students have NOT finished all their classes



select s.code
from programs p inner join students s on (p.degree = s.degree)
left outer join exams e on (e.course = p.course and e.student = s.code)
where e.course is null


We join programs with students and then left outer join the exams and filter only those rows where no exam row could be matched (which means the student has not taken the exam yet)



2) We get all students that are NOT returned by this query (meaning they have finished all required courses)



select
code, name
from student where code not in (

select s.code
from programs p inner join students s on (p.degree = s.degree)
left outer join exams e on (e.course = p.course and e.student = s.code)
where e.course is null

)





share|improve this answer

































    0














    I like using aggregation for these things.



    select s.code, s.name, s.degree
    from students s join
    programs p
    on p.degree = s.degree join
    exams e
    on e.student = s.code and e.course = p.course
    group by s.code, s.name, s.degree
    having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);


    Note that this includes the degree as well as the student. After all, students could double major.






    share|improve this answer































      0














      In a similar vein to Preli's answer, I'd use a left join to highlight exams that had not been taken:



      SELECT s.code, s.name, p.course
      FROM
      students s
      INNER JOIN
      programs p
      ON (p.degree = s.degree)


      This is effectively the list of exams a student must take for the course



      Now add on the exams they have taken, and leave nulls for those they havent:



      SELECT s.code, s.name, p.course, e.course
      FROM
      students s
      INNER JOIN
      programs p
      ON (p.degree = s.degree)

      LEFT OUTER JOIN
      exams e
      ON e.student = s.code AND e.course = p.course


      The results would look like:



      Code   | Name | p.Course | e.Course
      stu001 | John | Calc A | Calc A
      stu001 | John | Calc B | Calc B
      stu002 | Doe | Calc A | <null>
      stu002 | Doe | Calc B | <null>


      Now reduce it to a list of just students that have taken an exam for every course. We can do this by checking that the COUNT(e.course) is the same as the COUNT(p.course) because NULL isn't counted by COUNT() so any occurrences of null (no exam) in e.course reduce the count, compared to counting the overall occurrences of p.course (i could also have used count(*)):



      SELECT s.code, s.name
      FROM
      students s
      INNER JOIN
      programs p
      ON (p.degree = s.degree)

      LEFT OUTER JOIN
      exams e
      ON e.student = s.code AND e.course = p.course

      GROUP BY s.code, s.name
      HAVING COUNT(p.course) = COUNT(e.course)


      John's COUNT(p.Course) would be 2 and COUNT(e.course) would also be 2, so he shows (just once, because he's grouped. Doe's COUNT(p.course) is 2 but COUNT(e.course) is 0, because all values are null, and 2 != 0 so he is hidden






      share|improve this answer


























        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53053400%2fstudents-who-have-taken-the-test-for-every-course-in-their-degree%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        0














        Not sure if this is possible with just INNER JOIN, UNION, and CASE -> but I found a solution with an outer join (still quite simple).



        Lets try to solve this in two steps.



        1) Lets see which students have NOT finished all their classes



        select s.code
        from programs p inner join students s on (p.degree = s.degree)
        left outer join exams e on (e.course = p.course and e.student = s.code)
        where e.course is null


        We join programs with students and then left outer join the exams and filter only those rows where no exam row could be matched (which means the student has not taken the exam yet)



        2) We get all students that are NOT returned by this query (meaning they have finished all required courses)



        select
        code, name
        from student where code not in (

        select s.code
        from programs p inner join students s on (p.degree = s.degree)
        left outer join exams e on (e.course = p.course and e.student = s.code)
        where e.course is null

        )





        share|improve this answer






























          0














          Not sure if this is possible with just INNER JOIN, UNION, and CASE -> but I found a solution with an outer join (still quite simple).



          Lets try to solve this in two steps.



          1) Lets see which students have NOT finished all their classes



          select s.code
          from programs p inner join students s on (p.degree = s.degree)
          left outer join exams e on (e.course = p.course and e.student = s.code)
          where e.course is null


          We join programs with students and then left outer join the exams and filter only those rows where no exam row could be matched (which means the student has not taken the exam yet)



          2) We get all students that are NOT returned by this query (meaning they have finished all required courses)



          select
          code, name
          from student where code not in (

          select s.code
          from programs p inner join students s on (p.degree = s.degree)
          left outer join exams e on (e.course = p.course and e.student = s.code)
          where e.course is null

          )





          share|improve this answer




























            0












            0








            0







            Not sure if this is possible with just INNER JOIN, UNION, and CASE -> but I found a solution with an outer join (still quite simple).



            Lets try to solve this in two steps.



            1) Lets see which students have NOT finished all their classes



            select s.code
            from programs p inner join students s on (p.degree = s.degree)
            left outer join exams e on (e.course = p.course and e.student = s.code)
            where e.course is null


            We join programs with students and then left outer join the exams and filter only those rows where no exam row could be matched (which means the student has not taken the exam yet)



            2) We get all students that are NOT returned by this query (meaning they have finished all required courses)



            select
            code, name
            from student where code not in (

            select s.code
            from programs p inner join students s on (p.degree = s.degree)
            left outer join exams e on (e.course = p.course and e.student = s.code)
            where e.course is null

            )





            share|improve this answer















            Not sure if this is possible with just INNER JOIN, UNION, and CASE -> but I found a solution with an outer join (still quite simple).



            Lets try to solve this in two steps.



            1) Lets see which students have NOT finished all their classes



            select s.code
            from programs p inner join students s on (p.degree = s.degree)
            left outer join exams e on (e.course = p.course and e.student = s.code)
            where e.course is null


            We join programs with students and then left outer join the exams and filter only those rows where no exam row could be matched (which means the student has not taken the exam yet)



            2) We get all students that are NOT returned by this query (meaning they have finished all required courses)



            select
            code, name
            from student where code not in (

            select s.code
            from programs p inner join students s on (p.degree = s.degree)
            left outer join exams e on (e.course = p.course and e.student = s.code)
            where e.course is null

            )






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Oct 29 '18 at 21:23

























            answered Oct 29 '18 at 21:15









            PreliPreli

            1,56362742




            1,56362742

























                0














                I like using aggregation for these things.



                select s.code, s.name, s.degree
                from students s join
                programs p
                on p.degree = s.degree join
                exams e
                on e.student = s.code and e.course = p.course
                group by s.code, s.name, s.degree
                having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);


                Note that this includes the degree as well as the student. After all, students could double major.






                share|improve this answer




























                  0














                  I like using aggregation for these things.



                  select s.code, s.name, s.degree
                  from students s join
                  programs p
                  on p.degree = s.degree join
                  exams e
                  on e.student = s.code and e.course = p.course
                  group by s.code, s.name, s.degree
                  having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);


                  Note that this includes the degree as well as the student. After all, students could double major.






                  share|improve this answer


























                    0












                    0








                    0







                    I like using aggregation for these things.



                    select s.code, s.name, s.degree
                    from students s join
                    programs p
                    on p.degree = s.degree join
                    exams e
                    on e.student = s.code and e.course = p.course
                    group by s.code, s.name, s.degree
                    having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);


                    Note that this includes the degree as well as the student. After all, students could double major.






                    share|improve this answer













                    I like using aggregation for these things.



                    select s.code, s.name, s.degree
                    from students s join
                    programs p
                    on p.degree = s.degree join
                    exams e
                    on e.student = s.code and e.course = p.course
                    group by s.code, s.name, s.degree
                    having count(distinct e.course) = (select count(*) from programs p2 where p2.degree = p.degree);


                    Note that this includes the degree as well as the student. After all, students could double major.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Oct 29 '18 at 22:21









                    Gordon LinoffGordon Linoff

                    794k37318423




                    794k37318423























                        0














                        In a similar vein to Preli's answer, I'd use a left join to highlight exams that had not been taken:



                        SELECT s.code, s.name, p.course
                        FROM
                        students s
                        INNER JOIN
                        programs p
                        ON (p.degree = s.degree)


                        This is effectively the list of exams a student must take for the course



                        Now add on the exams they have taken, and leave nulls for those they havent:



                        SELECT s.code, s.name, p.course, e.course
                        FROM
                        students s
                        INNER JOIN
                        programs p
                        ON (p.degree = s.degree)

                        LEFT OUTER JOIN
                        exams e
                        ON e.student = s.code AND e.course = p.course


                        The results would look like:



                        Code   | Name | p.Course | e.Course
                        stu001 | John | Calc A | Calc A
                        stu001 | John | Calc B | Calc B
                        stu002 | Doe | Calc A | <null>
                        stu002 | Doe | Calc B | <null>


                        Now reduce it to a list of just students that have taken an exam for every course. We can do this by checking that the COUNT(e.course) is the same as the COUNT(p.course) because NULL isn't counted by COUNT() so any occurrences of null (no exam) in e.course reduce the count, compared to counting the overall occurrences of p.course (i could also have used count(*)):



                        SELECT s.code, s.name
                        FROM
                        students s
                        INNER JOIN
                        programs p
                        ON (p.degree = s.degree)

                        LEFT OUTER JOIN
                        exams e
                        ON e.student = s.code AND e.course = p.course

                        GROUP BY s.code, s.name
                        HAVING COUNT(p.course) = COUNT(e.course)


                        John's COUNT(p.Course) would be 2 and COUNT(e.course) would also be 2, so he shows (just once, because he's grouped. Doe's COUNT(p.course) is 2 but COUNT(e.course) is 0, because all values are null, and 2 != 0 so he is hidden






                        share|improve this answer






























                          0














                          In a similar vein to Preli's answer, I'd use a left join to highlight exams that had not been taken:



                          SELECT s.code, s.name, p.course
                          FROM
                          students s
                          INNER JOIN
                          programs p
                          ON (p.degree = s.degree)


                          This is effectively the list of exams a student must take for the course



                          Now add on the exams they have taken, and leave nulls for those they havent:



                          SELECT s.code, s.name, p.course, e.course
                          FROM
                          students s
                          INNER JOIN
                          programs p
                          ON (p.degree = s.degree)

                          LEFT OUTER JOIN
                          exams e
                          ON e.student = s.code AND e.course = p.course


                          The results would look like:



                          Code   | Name | p.Course | e.Course
                          stu001 | John | Calc A | Calc A
                          stu001 | John | Calc B | Calc B
                          stu002 | Doe | Calc A | <null>
                          stu002 | Doe | Calc B | <null>


                          Now reduce it to a list of just students that have taken an exam for every course. We can do this by checking that the COUNT(e.course) is the same as the COUNT(p.course) because NULL isn't counted by COUNT() so any occurrences of null (no exam) in e.course reduce the count, compared to counting the overall occurrences of p.course (i could also have used count(*)):



                          SELECT s.code, s.name
                          FROM
                          students s
                          INNER JOIN
                          programs p
                          ON (p.degree = s.degree)

                          LEFT OUTER JOIN
                          exams e
                          ON e.student = s.code AND e.course = p.course

                          GROUP BY s.code, s.name
                          HAVING COUNT(p.course) = COUNT(e.course)


                          John's COUNT(p.Course) would be 2 and COUNT(e.course) would also be 2, so he shows (just once, because he's grouped. Doe's COUNT(p.course) is 2 but COUNT(e.course) is 0, because all values are null, and 2 != 0 so he is hidden






                          share|improve this answer




























                            0












                            0








                            0







                            In a similar vein to Preli's answer, I'd use a left join to highlight exams that had not been taken:



                            SELECT s.code, s.name, p.course
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)


                            This is effectively the list of exams a student must take for the course



                            Now add on the exams they have taken, and leave nulls for those they havent:



                            SELECT s.code, s.name, p.course, e.course
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)

                            LEFT OUTER JOIN
                            exams e
                            ON e.student = s.code AND e.course = p.course


                            The results would look like:



                            Code   | Name | p.Course | e.Course
                            stu001 | John | Calc A | Calc A
                            stu001 | John | Calc B | Calc B
                            stu002 | Doe | Calc A | <null>
                            stu002 | Doe | Calc B | <null>


                            Now reduce it to a list of just students that have taken an exam for every course. We can do this by checking that the COUNT(e.course) is the same as the COUNT(p.course) because NULL isn't counted by COUNT() so any occurrences of null (no exam) in e.course reduce the count, compared to counting the overall occurrences of p.course (i could also have used count(*)):



                            SELECT s.code, s.name
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)

                            LEFT OUTER JOIN
                            exams e
                            ON e.student = s.code AND e.course = p.course

                            GROUP BY s.code, s.name
                            HAVING COUNT(p.course) = COUNT(e.course)


                            John's COUNT(p.Course) would be 2 and COUNT(e.course) would also be 2, so he shows (just once, because he's grouped. Doe's COUNT(p.course) is 2 but COUNT(e.course) is 0, because all values are null, and 2 != 0 so he is hidden






                            share|improve this answer















                            In a similar vein to Preli's answer, I'd use a left join to highlight exams that had not been taken:



                            SELECT s.code, s.name, p.course
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)


                            This is effectively the list of exams a student must take for the course



                            Now add on the exams they have taken, and leave nulls for those they havent:



                            SELECT s.code, s.name, p.course, e.course
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)

                            LEFT OUTER JOIN
                            exams e
                            ON e.student = s.code AND e.course = p.course


                            The results would look like:



                            Code   | Name | p.Course | e.Course
                            stu001 | John | Calc A | Calc A
                            stu001 | John | Calc B | Calc B
                            stu002 | Doe | Calc A | <null>
                            stu002 | Doe | Calc B | <null>


                            Now reduce it to a list of just students that have taken an exam for every course. We can do this by checking that the COUNT(e.course) is the same as the COUNT(p.course) because NULL isn't counted by COUNT() so any occurrences of null (no exam) in e.course reduce the count, compared to counting the overall occurrences of p.course (i could also have used count(*)):



                            SELECT s.code, s.name
                            FROM
                            students s
                            INNER JOIN
                            programs p
                            ON (p.degree = s.degree)

                            LEFT OUTER JOIN
                            exams e
                            ON e.student = s.code AND e.course = p.course

                            GROUP BY s.code, s.name
                            HAVING COUNT(p.course) = COUNT(e.course)


                            John's COUNT(p.Course) would be 2 and COUNT(e.course) would also be 2, so he shows (just once, because he's grouped. Doe's COUNT(p.course) is 2 but COUNT(e.course) is 0, because all values are null, and 2 != 0 so he is hidden







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Oct 30 '18 at 8:45

























                            answered Oct 30 '18 at 8:38









                            Caius JardCaius Jard

                            12.5k21440




                            12.5k21440






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53053400%2fstudents-who-have-taken-the-test-for-every-course-in-their-degree%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                這個網誌中的熱門文章

                                Xamarin.form Move up view when keyboard appear

                                Post-Redirect-Get with Spring WebFlux and Thymeleaf

                                Anylogic : not able to use stopDelay()