Fritze: SQL-Knobelei

Beitrag lesen

Problem ist gelöst, eine Verständnisfrage habe ich aber dennoch:

select * from alt  
  left join produkt on alt.name=produkt.name and if(alt.nummer is null,produkt.alt is null,alt.nummer=produkt.alt)  
  left join regal on alt.regal=regal.alt  
  left join fach on alt.fach=fach.alt and regal.id=fach.regal;

| alt                               | produkt                 | regal       | fach
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+
| name      | nummer | regal | fach | id   | name      | alt  | id   | alt  | id   | alt  | regal |
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+
| Knüsperdü |     23 |     1 |    2 |    1 | Knüsperdü |   23 |    1 |    1 |    1 |    2 |     1 |
| Knüsperdü |   NULL |     3 |    8 |    2 | Knüsperdü | NULL |    2 |    3 |    3 |    8 |     2 |
| Pustekuh  |   NULL |     5 |    2 |    3 | Pustekuh  | NULL |    3 |    5 |    4 |    2 |     3 |
| Rattelfix |     42 |     5 | NULL |    4 | Rattelfix |   42 |    3 |    5 | NULL | NULL |  NULL |
| Sausemaus |   NULL |     1 |    4 |    5 | Sausemaus | NULL |    1 |    1 |    2 |    4 |     1 |
| Sausemaus |   NULL |     3 |    6 |    5 | Sausemaus | NULL |    2 |    3 |    5 |    6 |     2 |
| Sausemaus |   NULL |     3 | NULL |    5 | Sausemaus | NULL |    2 |    3 | NULL | NULL |  NULL |
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+

select * from alt  
  left join produkt on alt.name=produkt.name and alt.nummer=produkt.alt  
  left join regal on alt.regal=regal.alt  
  left join fach on alt.fach=fach.alt and regal.id=fach.regal;

| alt                               | produkt                 | regal       | fach
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+
| name      | nummer | regal | fach | id   | name      | alt  | id   | alt  | id   | alt  | regal |
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+
| Knüsperdü |     23 |     1 |    2 |    1 | Knüsperdü |   23 |    1 |    1 |    1 |    2 |     1 |
| Knüsperdü |   NULL |     3 |    8 | NULL | NULL      | NULL |    2 |    3 |    3 |    8 |     2 |
| Pustekuh  |   NULL |     5 |    2 | NULL | NULL      | NULL |    3 |    5 |    4 |    2 |     3 |
| Rattelfix |     42 |     5 | NULL |    4 | Rattelfix |   42 |    3 |    5 | NULL | NULL |  NULL |
| Sausemaus |   NULL |     1 |    4 | NULL | NULL      | NULL |    1 |    1 |    2 |    4 |     1 |
| Sausemaus |   NULL |     3 |    6 | NULL | NULL      | NULL |    2 |    3 |    5 |    6 |     2 |
| Sausemaus |   NULL |     3 | NULL | NULL | NULL      | NULL |    2 |    3 | NULL | NULL |  NULL |
+-----------+--------+-------+------+------+-----------+------+------+------+------+------+-------+

Die beiden Befehle unterscheiden sich in

if(alt.nummer is null,produkt.alt is null,alt.nummer=produkt.alt)
gegenüber
  alt.nummer=produkt.alt

Warum gibt es bei der ersten Variante Daten bei allen produkt.id-Zeilen, bei der zweiten jedoch nur dort, wenn alt.nummer nicht NULL ist?

Datenbank ist MySQL 5.0.

Quelltabellen:
--------------

alt
+-----------+--------+-------+------+
| name      | nummer | regal | fach |
+-----------+--------+-------+------+
| Knüsperdü |     23 |     1 |    2 |
| Knüsperdü |   NULL |     3 |    8 |
| Pustekuh  |   NULL |     5 |    2 |
| Rattelfix |     42 |     5 | NULL |
| Sausemaus |   NULL |     1 |    4 |
| Sausemaus |   NULL |     3 |    6 |
| Sausemaus |   NULL |     3 | NULL |
+-----------+--------+-------+------+

regal
+------+------+
| id   | alt  |
+------+------+
|    1 |    1 |
|    2 |    3 |
|    3 |    5 |
+------+------+
regal.id: Neue Seriennummer
regal.alt = alt.regalnummer

fach
+------+------+-------+
| id   | alt  | regal |
+------+------+-------+
|    1 |    2 |     1 |
|    2 |    4 |     1 |
|    3 |    8 |     2 |
|    4 |    2 |     3 |
|    5 |    6 |     2 |
+------+------+-------+
fach.id: Neue Seriennummer (jetzt global eindeutig, nicht nur pro Regal)
fach.alt = alt.fachnummer
fach.regal <-> regal.id

produkt
+------+-----------+------+
| id   | name      | alt  |
+------+-----------+------+
|    1 | Knüsperdü |   23 |
|    2 | Knüsperdü | NULL |
|    3 | Pustekuh  | NULL |
|    4 | Rattelfix |   42 |
|    5 | Sausemaus | NULL |
+------+-----------+------+
produkt.id   = Neue Seriennummer (jetzt für alle Produkte ein Eintrag)
produkt.name = alt.produktname
produkt.alt  = alt.produktnummer

Befehle zum Erzeugen der Probiertabellen:
-----------------------------------------

create table alt (name varchar(32),nummer int,regal int, fach int);
create table regal (id int, alt int);
create table fach (id int, alt int, regal int);
create table produkt (id int, name varchar(32), alt int);
create table lager (produkt int, regal int, fach int, name varchar(32));

insert into alt (name,nummer,regal,fach) values ("Knüsperdü",23,1,2), ("Knüsperdü",null,3,8), ("Pustekuh",null,5,2), ("Rattelfix",42,5,null), ("Sausemaus",null,1,4), ("Sausemaus",null,3,6), ("Sausemaus",null,3,null);
insert into regal (id,alt) values (1,1),(2,3),(3,5);
insert into fach (id,alt,regal) values (1,2,1),(2,4,1),(3,8,2),(4,2,3),(5,6,2);
insert into produkt (id,name,alt) values (1,"Knüsperdü",23), (2,"Knüsperdü",null), (3,"Pustekuh",null), (4,"Rattelfix",42), (5,"Sausemaus",null);