Comparing columns values and change their places by condition

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite
1












There are three simple tables. Actor, Film, Film_actor.



Film_Actor table:



 actor_id | film_id
--------------+---------------------------
1 | 3
2 | 4


Actor table:



 actor_id | first_name | last_name
------------+-----------------------------+----------
1 | Daniel | Craig
2 | Eva | Green


Film table:



 film_id | title 
-------------+---------------------------------------
3 | Casino Royale
4 | Colombo


I would like to find two actors who cast together the most and list the titles
of those movies. Moreover, actor_id of the first_actor should be lower than actor_id of the second_actor
.



So the desired result should look like this:



first_actor | second_actor | title
----------------+---------------+---------------
Daniel Craig | Eva Green | Casino Royale


I've written the following code:



SELECT 
ac1.actor_id first_actor_id
, ac1.first_name + ' ' + ac1.last_name first_actor
, ac2.actor_id second_actor_id
, ac2.first_name + ' ' + ac2.last_name second_actor
,count(*) FilmCount
FROM
Actor as ac1
INNER JOIN Film_Actor as fa1 ON fa1.actor_id = ac1.actor_id
INNER JOIN Film_Actor as fa2 ON fa1.film_id = fa2.film_id
INNER JOIN Actor as ac2 ON fa2.actor_id = ac2.actor_id
and fa1.actor_id < ac2.actor_id
INNER JOIN Film as fi ON fa1.film_id = fi.film_id
GROUP BY
ac1.actor_id
, ac1.first_name
, ac1.last_name
, ac2.actor_id
, ac2.first_name
, ac2.last_name


In my view, the above code is a little bit clumsy as the code makes checking of this condition actor_id of the first_actor should be lower than actor_id of the second_actor*` just for second actor.



Is it possible to improve comparing actor_id of the first_actor with actor_id of the second_actor`?







share|improve this question



























    up vote
    3
    down vote

    favorite
    1












    There are three simple tables. Actor, Film, Film_actor.



    Film_Actor table:



     actor_id | film_id
    --------------+---------------------------
    1 | 3
    2 | 4


    Actor table:



     actor_id | first_name | last_name
    ------------+-----------------------------+----------
    1 | Daniel | Craig
    2 | Eva | Green


    Film table:



     film_id | title 
    -------------+---------------------------------------
    3 | Casino Royale
    4 | Colombo


    I would like to find two actors who cast together the most and list the titles
    of those movies. Moreover, actor_id of the first_actor should be lower than actor_id of the second_actor
    .



    So the desired result should look like this:



    first_actor | second_actor | title
    ----------------+---------------+---------------
    Daniel Craig | Eva Green | Casino Royale


    I've written the following code:



    SELECT 
    ac1.actor_id first_actor_id
    , ac1.first_name + ' ' + ac1.last_name first_actor
    , ac2.actor_id second_actor_id
    , ac2.first_name + ' ' + ac2.last_name second_actor
    ,count(*) FilmCount
    FROM
    Actor as ac1
    INNER JOIN Film_Actor as fa1 ON fa1.actor_id = ac1.actor_id
    INNER JOIN Film_Actor as fa2 ON fa1.film_id = fa2.film_id
    INNER JOIN Actor as ac2 ON fa2.actor_id = ac2.actor_id
    and fa1.actor_id < ac2.actor_id
    INNER JOIN Film as fi ON fa1.film_id = fi.film_id
    GROUP BY
    ac1.actor_id
    , ac1.first_name
    , ac1.last_name
    , ac2.actor_id
    , ac2.first_name
    , ac2.last_name


    In my view, the above code is a little bit clumsy as the code makes checking of this condition actor_id of the first_actor should be lower than actor_id of the second_actor*` just for second actor.



    Is it possible to improve comparing actor_id of the first_actor with actor_id of the second_actor`?







    share|improve this question























      up vote
      3
      down vote

      favorite
      1









      up vote
      3
      down vote

      favorite
      1






      1





      There are three simple tables. Actor, Film, Film_actor.



      Film_Actor table:



       actor_id | film_id
      --------------+---------------------------
      1 | 3
      2 | 4


      Actor table:



       actor_id | first_name | last_name
      ------------+-----------------------------+----------
      1 | Daniel | Craig
      2 | Eva | Green


      Film table:



       film_id | title 
      -------------+---------------------------------------
      3 | Casino Royale
      4 | Colombo


      I would like to find two actors who cast together the most and list the titles
      of those movies. Moreover, actor_id of the first_actor should be lower than actor_id of the second_actor
      .



      So the desired result should look like this:



      first_actor | second_actor | title
      ----------------+---------------+---------------
      Daniel Craig | Eva Green | Casino Royale


      I've written the following code:



      SELECT 
      ac1.actor_id first_actor_id
      , ac1.first_name + ' ' + ac1.last_name first_actor
      , ac2.actor_id second_actor_id
      , ac2.first_name + ' ' + ac2.last_name second_actor
      ,count(*) FilmCount
      FROM
      Actor as ac1
      INNER JOIN Film_Actor as fa1 ON fa1.actor_id = ac1.actor_id
      INNER JOIN Film_Actor as fa2 ON fa1.film_id = fa2.film_id
      INNER JOIN Actor as ac2 ON fa2.actor_id = ac2.actor_id
      and fa1.actor_id < ac2.actor_id
      INNER JOIN Film as fi ON fa1.film_id = fi.film_id
      GROUP BY
      ac1.actor_id
      , ac1.first_name
      , ac1.last_name
      , ac2.actor_id
      , ac2.first_name
      , ac2.last_name


      In my view, the above code is a little bit clumsy as the code makes checking of this condition actor_id of the first_actor should be lower than actor_id of the second_actor*` just for second actor.



      Is it possible to improve comparing actor_id of the first_actor with actor_id of the second_actor`?







      share|improve this question













      There are three simple tables. Actor, Film, Film_actor.



      Film_Actor table:



       actor_id | film_id
      --------------+---------------------------
      1 | 3
      2 | 4


      Actor table:



       actor_id | first_name | last_name
      ------------+-----------------------------+----------
      1 | Daniel | Craig
      2 | Eva | Green


      Film table:



       film_id | title 
      -------------+---------------------------------------
      3 | Casino Royale
      4 | Colombo


      I would like to find two actors who cast together the most and list the titles
      of those movies. Moreover, actor_id of the first_actor should be lower than actor_id of the second_actor
      .



      So the desired result should look like this:



      first_actor | second_actor | title
      ----------------+---------------+---------------
      Daniel Craig | Eva Green | Casino Royale


      I've written the following code:



      SELECT 
      ac1.actor_id first_actor_id
      , ac1.first_name + ' ' + ac1.last_name first_actor
      , ac2.actor_id second_actor_id
      , ac2.first_name + ' ' + ac2.last_name second_actor
      ,count(*) FilmCount
      FROM
      Actor as ac1
      INNER JOIN Film_Actor as fa1 ON fa1.actor_id = ac1.actor_id
      INNER JOIN Film_Actor as fa2 ON fa1.film_id = fa2.film_id
      INNER JOIN Actor as ac2 ON fa2.actor_id = ac2.actor_id
      and fa1.actor_id < ac2.actor_id
      INNER JOIN Film as fi ON fa1.film_id = fi.film_id
      GROUP BY
      ac1.actor_id
      , ac1.first_name
      , ac1.last_name
      , ac2.actor_id
      , ac2.first_name
      , ac2.last_name


      In my view, the above code is a little bit clumsy as the code makes checking of this condition actor_id of the first_actor should be lower than actor_id of the second_actor*` just for second actor.



      Is it possible to improve comparing actor_id of the first_actor with actor_id of the second_actor`?









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 8 at 16:57
























      asked Jan 8 at 16:48









      Learner

      184




      184




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          3
          down vote



          accepted










          Since inner joins are used, you'll only ever be returned rows where the first_actor_id is smaller than the second_actor_id, so the code works as intended.



          If I understand correctly, you want the code to check that first_actor_id is smaller than second_actor_id AND second_actor_id is bigger than first_actor_id. However, those two conditions are the same so you only need one of them.



          As a sidenote, your code will not work as intended for the following reasons: (1) It will bring back any actors who have starred in ONE movie together, rather than two, and (2) it does not list the movie names they have starred in.



          The first problem is easy to fix; add HAVING count(*) >= 2 to the end of the statement.



          The second problem depends on the version of SQL Server you are using (use SELECT @@VERSION to find out):



          • If you're running SQL Server 2017 or later, exchange count(*) in the SELECT for STRING_AGG(fi.title, ', ') (documentation linked) – this will give you a comma-separated list of films.

          • If not, the best way to concatenate strings from a group is the "stuff XML path" method. A quick search online should explain how this trick works.





          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            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: "196"
            ;
            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',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184595%2fcomparing-columns-values-and-change-their-places-by-condition%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            3
            down vote



            accepted










            Since inner joins are used, you'll only ever be returned rows where the first_actor_id is smaller than the second_actor_id, so the code works as intended.



            If I understand correctly, you want the code to check that first_actor_id is smaller than second_actor_id AND second_actor_id is bigger than first_actor_id. However, those two conditions are the same so you only need one of them.



            As a sidenote, your code will not work as intended for the following reasons: (1) It will bring back any actors who have starred in ONE movie together, rather than two, and (2) it does not list the movie names they have starred in.



            The first problem is easy to fix; add HAVING count(*) >= 2 to the end of the statement.



            The second problem depends on the version of SQL Server you are using (use SELECT @@VERSION to find out):



            • If you're running SQL Server 2017 or later, exchange count(*) in the SELECT for STRING_AGG(fi.title, ', ') (documentation linked) – this will give you a comma-separated list of films.

            • If not, the best way to concatenate strings from a group is the "stuff XML path" method. A quick search online should explain how this trick works.





            share|improve this answer

























              up vote
              3
              down vote



              accepted










              Since inner joins are used, you'll only ever be returned rows where the first_actor_id is smaller than the second_actor_id, so the code works as intended.



              If I understand correctly, you want the code to check that first_actor_id is smaller than second_actor_id AND second_actor_id is bigger than first_actor_id. However, those two conditions are the same so you only need one of them.



              As a sidenote, your code will not work as intended for the following reasons: (1) It will bring back any actors who have starred in ONE movie together, rather than two, and (2) it does not list the movie names they have starred in.



              The first problem is easy to fix; add HAVING count(*) >= 2 to the end of the statement.



              The second problem depends on the version of SQL Server you are using (use SELECT @@VERSION to find out):



              • If you're running SQL Server 2017 or later, exchange count(*) in the SELECT for STRING_AGG(fi.title, ', ') (documentation linked) – this will give you a comma-separated list of films.

              • If not, the best way to concatenate strings from a group is the "stuff XML path" method. A quick search online should explain how this trick works.





              share|improve this answer























                up vote
                3
                down vote



                accepted







                up vote
                3
                down vote



                accepted






                Since inner joins are used, you'll only ever be returned rows where the first_actor_id is smaller than the second_actor_id, so the code works as intended.



                If I understand correctly, you want the code to check that first_actor_id is smaller than second_actor_id AND second_actor_id is bigger than first_actor_id. However, those two conditions are the same so you only need one of them.



                As a sidenote, your code will not work as intended for the following reasons: (1) It will bring back any actors who have starred in ONE movie together, rather than two, and (2) it does not list the movie names they have starred in.



                The first problem is easy to fix; add HAVING count(*) >= 2 to the end of the statement.



                The second problem depends on the version of SQL Server you are using (use SELECT @@VERSION to find out):



                • If you're running SQL Server 2017 or later, exchange count(*) in the SELECT for STRING_AGG(fi.title, ', ') (documentation linked) – this will give you a comma-separated list of films.

                • If not, the best way to concatenate strings from a group is the "stuff XML path" method. A quick search online should explain how this trick works.





                share|improve this answer













                Since inner joins are used, you'll only ever be returned rows where the first_actor_id is smaller than the second_actor_id, so the code works as intended.



                If I understand correctly, you want the code to check that first_actor_id is smaller than second_actor_id AND second_actor_id is bigger than first_actor_id. However, those two conditions are the same so you only need one of them.



                As a sidenote, your code will not work as intended for the following reasons: (1) It will bring back any actors who have starred in ONE movie together, rather than two, and (2) it does not list the movie names they have starred in.



                The first problem is easy to fix; add HAVING count(*) >= 2 to the end of the statement.



                The second problem depends on the version of SQL Server you are using (use SELECT @@VERSION to find out):



                • If you're running SQL Server 2017 or later, exchange count(*) in the SELECT for STRING_AGG(fi.title, ', ') (documentation linked) – this will give you a comma-separated list of films.

                • If not, the best way to concatenate strings from a group is the "stuff XML path" method. A quick search online should explain how this trick works.






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered Jan 10 at 16:42









                Kris Lawton

                1509




                1509






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184595%2fcomparing-columns-values-and-change-their-places-by-condition%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Python Lists

                    Aion

                    JavaScript Array Iteration Methods