Here's a mini-tutorial on left join that should solve your problem.

First, let's make a smaller example.  (It would have been helpful if
you had done that and formatted your select so it could be read when
you posted the question ;-)  Here are 2 tables:

select * from header;            select * from placement;
+------+                         +------+-----------+
| code |                         | code | product   |
+------+                         +------+-----------+
|    6 |                         |    6 | NOSUCH    |
|    7 |                         |    7 | OVRLCKBDG |
|    8 |                         |    7 | FUBAR     |
+------+                         +------+-----------+

You want:
  Info for header 6, and, if any, info for placement (6, '1029106')
  Info for header 7, and, if any, info for placement (7, 'OVRLCKBDG')

Let's look at what a left join is.  For a SQL query,
    select A.*, B.* from A left join B on <condition>;
returns two things,
    (1)  Matching rows from A and B, as would be returned by
        SELECT A.*, B.* from A, B where <condition>;
    (2)  Rows of the form A.*, null, ..., null  where those rows
        in A are included that do NOT participate in the match
        in (1), followed by nulls representing the columns of B.

So, in our example,

    select header.*, placement.*
      from header
        left join placement
          on header.code = placement.code;

gives us all of the header codes and the matching placements:
+------+------+-----------+
| code | code | product   |
+------+------+-----------+
|    6 |    6 | NOSUCH    |
|    7 |    7 | OVRLCKBDG |
|    7 |    7 | FUBAR     |
|    8 | NULL | NULL      |
+------+------+-----------+

Well, we don't want all of the matching placements; we just want the
specific matches listed above.  So, let's add these to the left
join condition:

    select header.*, placement.*
      from header
        left join placement
          on header.code = placement.code
            and ( header.code = 6 and placement.product = '1029106'
               or header.code = 7 and placement.product = 'OVRLCKBDG' );

This gives us the placements we want, but there are too many headers:
+------+------+-----------+
| code | code | product   |
+------+------+-----------+
|    6 | NULL | NULL      |
|    7 |    7 | OVRLCKBDG |
|    8 | NULL | NULL      |
+------+------+-----------+

So. finally, we get rid of the extra headers by adding a where clause:

    select header.*, placement.*
      from header
        left join placement
          on header.code = placement.code
            and ( header.code = 6 and placement.product = '1029106'
               or header.code = 7 and placement.product = 'OVRLCKBDG' )
      where header.code in (6, 7);

This gives the desired result:
+------+------+-----------+
| code | code | product   |
+------+------+-----------+
|    6 | NULL | NULL      |
|    7 |    7 | OVRLCKBDG |
+------+------+-----------+


====================

This is a bit ugly, in that the header.code's are listed twice, and there
are a lot of literals in the select statement.  It might be better to
use a temporary table to hold the desired (code, product) pairs.  Then,
we join the 3 tables with a select that seems less complex:

Here's the temporary table:

select * from tt;
+------+-----------+
| code | product   |
+------+-----------+
|    6 | 1029106   |
|    7 | OVRLCKBDG |
+------+-----------+

and here's the 3-table join:

    select header.*, placement.*
      from header
        inner join tt
          on header.code = tt.code
        left join placement
          on tt.code = placement.code
            and tt.product = placement.product;

which also gives the desired result:
+------+------+-----------+
| code | code | product   |
+------+------+-----------+
|    6 | NULL | NULL      |
|    7 |    7 | OVRLCKBDG |
+------+------+-----------+

> From: "Mark Colvin" <[EMAIL PROTECTED]>
> To: "MySQL Mailing List \(E-mail\)" <[EMAIL PROTECTED]>
> Subject: MySQL Left Join Query
> Date: Mon, 18 Nov 2002 08:05:51 -0000
>
> I have a two table query where I want to return records from the first
table
> and if they have corresponding details in my second table I wish to return
> those as well. A sample sql statement I am using is as follows:
>
> select decheader.code, decheader.height, decheader.width,
> decplacement.position, decplacement.product from decheader left join
> decplacement on decheader.code = decplacement.code where (decheader.code =
> '00007' and decplacement.product = 'OVRLCKBDG') or (decheader.code =
'00006'
> and decplacement.product = '1029106') or (decheader.code = '00005' and
> decplacement.product = '1029103') or (decheader.code = '00005' and
> decplacement.product = '1029104') or (decheader.code = '00005' and
> decplacement.product = '1029105') or (decheader.code = '00005' and
> decplacement.product = '1029106') or (decheader.code = '00004' and
> decplacement.product = '1029104') or (decheader.code = '00004' and
> decplacement.product = '1029105')
>
> In the above example, all of the codes exist in the decheader table but
only
> code 00007 has a corresponding product in the decplacement table. I would
> wish to return all the decheader details for the above codes and the
> decplacement details for code 00007 as well. This statement actually only
> gives me the details for code 0007 and nothing else. I should add that for
> each record in the decheader table, there may be one, none or many
recordsh
> in the decplacement table but I will only be interested in a specific one.
I
> hope this makes some sort of sense!!



---------------------------------------------------------------------
Before posting, please check:
   http://www.mysql.com/manual.php   (the manual)
   http://lists.mysql.com/           (the list archive)

To request this thread, e-mail <[EMAIL PROTECTED]>
To unsubscribe, e-mail <[EMAIL PROTECTED]>
Trouble unsubscribing? Try: http://lists.mysql.com/php/unsubscribe.php

Reply via email to