• Visitors can check out the Forum FAQ by clicking this link. You have to register before you can post: click the REGISTER link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. View our Forum Privacy Policy.
  • Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

SQL Left Join

Collapse
X
  •  
  • Filter
  • Time
  • Show
Clear All
new posts

    SQL Left Join

    Apologies if this is is a very basic question but my SQL is a bit rusty these days.

    Simple scenario, I have 2 tables, A & B and I want to return everything form table A that doesn't have a corresponding record in B. So I've tried the followwing 2 statements:

    SELECT a.* FROM TableA a
    LEFT JOIN TableB b ON a.id = b.id
    WHERE b.id IS NULL

    SELECT a.* FROM TableA a
    LEFT JOIN TableB b ON (a.id = b.id AND b.id IS NULL)

    They both return different results. I would have expected the results to be same for both.

    What approach is correct?

    #2
    Originally posted by wurzel View Post
    What approach is correct?
    The first one
    Coffee's for closers

    Comment


      #3
      Originally posted by wurzel View Post
      What approach is correct?
      It depends on what you want

      Originally posted by wurzel View Post
      SELECT a.* FROM TableA a
      LEFT JOIN TableB b ON a.id = b.id
      WHERE b.id IS NULL

      SELECT a.* FROM TableA a
      LEFT JOIN TableB b ON (a.id = b.id AND b.id IS NULL)
      The difference is that the join condition in the second cursor may return no rows (there are no rows in b with a null ID). This means that (a.id=b.id AND b.id IS NULL) essentially means that you return everything in TableA.

      Code:
      SQL > CREATE table CUK1 (id number);
      
      Table created.
      
      Elapsed: 00:00:00.48
      SQL > begin
        2    for i in 1..4 loop
        3      insert into cuk1 values (i);
        4    end loop;
        5    commit;
        6  end;
        7  /
      
      PL/SQL procedure successfully completed.
      
      Elapsed: 00:00:00.46
      SQL >
      SQL > create table cuk2 (id number);
      
      Table created.
      
      Elapsed: 00:00:00.48
      SQL >
      SQL > begin
        2    for i in 3..4 loop
        3      insert into cuk2 values (i);
        4    end loop;
        5    commit;
        6  end;
        7  /
      
      PL/SQL procedure successfully completed.
      
      Elapsed: 00:00:00.48
      SQL > select * from cuk1;
      
              ID
      ----------
               1
               2
               3
               4
      
      Elapsed: 00:00:00.59
      SQL > select * from cuk2;
      
              ID
      ----------
               3
               4
      
      Elapsed: 00:00:00.59
      SQL > select cuk1.id, cuk2.id
        2  from   cuk1 LEFT OUTER JOIN cuk2 ON (cuk1.id = cuk2.id);
      
              ID         ID
      ---------- ----------
               3          3
               4          4
               1
               2
      
      Elapsed: 00:00:00.64
      SQL > SELECT a.* FROM cuk1 a
        2  LEFT JOIN cuk2 b ON a.id = b.id
        3  WHERE b.id IS NULL;
      
              ID
      ----------
               1
               2
      
      Elapsed: 00:00:00.61
      SQL > SELECT a.* FROM cuk1 a
        2  LEFT JOIN cuk2 b ON (a.id = b.id AND b.id IS NULL);
      
              ID
      ----------
               1
               2
               3
               4
      
      Elapsed: 00:00:00.60
      SQL > SELECT a.*
        2  FROM   cuk1 a
        3  JOIN   cuk2 b ON ( a.id = b.id );
      
              ID
      ----------
               3
               4
      
      Elapsed: 00:00:00.62
      SQL > SELECT a.* FROM cuk1 a
        2  LEFT JOIN cuk2 b ON a.id = b.id
        3  WHERE b.id IS NOT NULL;
      
              ID
      ----------
               3
               4
      
      Elapsed: 00:00:00.59
      SQL > drop table cuk1;
      
      Table dropped.
      
      Elapsed: 00:00:00.51
      SQL >
      SQL > drop table cuk2;
      
      Table dropped.
      
      Elapsed: 00:00:00.57
      SQL >
      Best Forum Advisor 2014
      Work in the public sector? You can read my FAQ here
      Click here to get 15% off your first year's IPSE membership

      Comment


        #4
        Originally posted by TheFaQQer View Post
        It depends on what you want
        Originally posted by wurzel View Post
        I want to return everything form table A that doesn't have a corresponding record in B.
        Ahem
        Coffee's for closers

        Comment


          #5
          Originally posted by Spacecadet View Post
          Ahem


          Didn't read that bit.
          Best Forum Advisor 2014
          Work in the public sector? You can read my FAQ here
          Click here to get 15% off your first year's IPSE membership

          Comment


            #6
            Wouldn't using a not exists clause work better?

            eg: select a* from tableA a
            where not exists (select * from TableB b where b.id=a.id)

            though

            select a* from TableA a left join TableB b on a.id=b.id
            where b.id IS NULL

            is another way to go.
            McCoy: "Medical men are trained in logic."
            Spock: "Trained? Judging from you, I would have guessed it was trial and error."

            Comment


              #7
              Originally posted by TheFaQQer View Post
              It depends on what you want



              The difference is that the join condition in the second cursor may return no rows (there are no rows in b with a null ID). This means that (a.id=b.id AND b.id IS NULL) essentially means that you return everything in TableA......
              Perfect thanks.

              Originally posted by lilelvis2000 View Post
              Wouldn't using a not exists clause work better?

              eg: select a* from tableA a
              where not exists (select * from TableB b where b.id=a.id)

              though

              select a* from TableA a left join TableB b on a.id=b.id
              where b.id IS NULL

              is another way to go.
              Would one perform better than the other?

              Comment


                #8
                Try this, makes sense to me

                Coding Horror: A Visual Explanation of SQL Joins
                Always forgive your enemies; nothing annoys them so much.

                Comment


                  #9
                  Originally posted by wurzel View Post
                  Perfect thanks.



                  Would one perform better than the other?
                  You would need to try it. go on.
                  McCoy: "Medical men are trained in logic."
                  Spock: "Trained? Judging from you, I would have guessed it was trial and error."

                  Comment


                    #10
                    Originally posted by wurzel View Post
                    Would one perform better than the other?
                    It depends on whether the column is nullable or not, and (probably) which database you are using.

                    In MySQL, for example, left join performs well where both columns are not-nullable. However, it performs badly where one or both of the columns is nullable, in which case an EXISTS / NOT EXISTS would perform better.

                    You could also use a NOT IN instead of NOT EXISTS, which (I think!) would work best, although if the column is nullable then you would need to include an additional check for nulls.
                    Best Forum Advisor 2014
                    Work in the public sector? You can read my FAQ here
                    Click here to get 15% off your first year's IPSE membership

                    Comment

                    Working...
                    X