# JOIN Abfrage über mehrere Tabellen



## Generic1 (14. Apr 2011)

Hallo,

meine DB- Kenntnisse sind schon ein bisschen verstaubt und deshalb hätte ich eine Frage in diese Richtung, und zwar hab ich folgendes DB- Schema:







Von der Event-  zum Teilnehmer - Tabelle und von der Teilnehmer- Tabelle zur Bezahlung- Tabelle besteht eine m:n- Beziehung (Also ein Teilnehmer kann an mehreren Events teilnehmen und kann/muss natürlich für die Events Eintrittsgeld bezahlen).

Meine Frage wäre jetzt, ob es möglich ist herauszufinden, ob ein Teilnehmer, welcher an einem bestimmten Event teilnimmt, schon bezahlt hat oder nicht, also:


```
Event        (m:n)          Teilnehmer       (m:n)      Bezahlung
----------------------------------------------------------
Ausstellung1                Hans Huber                      €0
Ausstellung2                Walter Meier                    €15
```

Also ich bräuchte eine SQL- Abfrage, welche mir ausgibt ob z.B.: der Herr Hans Huber für die Ausstellung1 schon bezahlt hat.

Ich weiß jetzt, dass das mit Joins gehen muss aber mir ist nicht mehr klar, wie ich das machen kann.

lg
Generic1


----------



## SlaterB (14. Apr 2011)

SQL JOIN - SQL Tutorial


----------



## Generic1 (14. Apr 2011)

OK, Join über 2 Tabellen, welche mit m:n verbunden sind ist klar, aber wie kann ich die Joins dann über 3 Tabellen machen?
lg und besten Dank,
lg


----------



## SlaterB (14. Apr 2011)

mit direkt verknüpften Tabellen syntaktisch vielleicht fraglich, 
das würde ich eh nicht am Anfang empfehlen (auch wenn vielleicht durch den Link getan)

die allgemeine Variante dürfte doch bekannt sein:

```
select a.g, b.r, d.z  // Auswahl
from A a, B b, C c, D d // Tabellen
where a.a = b.a and b.b = c.b and c.d = d.d // Verknüpfung der Tabellen
and a.x = 4 und c.y = 'heute' // sonstige Selektion
```


----------



## Gast2 (14. Apr 2011)

Erm... in dem Schema oben sehe ich gar keine Relation zwischen den Tabellen? Hast du da noch kreuztabellen zwischen oder eine der Splaten mit den relevanten Keys einfach ausgelassen?


----------



## Generic1 (14. Apr 2011)

fassy hat gesagt.:


> Erm... in dem Schema oben sehe ich gar keine Relation zwischen den Tabellen? Hast du da noch kreuztabellen zwischen oder eine der Splaten mit den relevanten Keys einfach ausgelassen?




bei den Relationen steht eh m:n!

eine Frage hätte ich noch zu diesem Thema, wenn ich folgenden 3 Tabellen habe:


```
Event              m:n                Teilnehmer              1:n                    Ergebnisse
Düsseldorf                             Hans Meier                                          4:45h
Dortmund                              Walter Müller                                       3:34h
                                                                                          2:40h
```

Also Hans Meier hat in Düsseldorf mitgemacht (z.B. Oltimerrennen) und hat 4:45h benötigt.
Walter Müller hat in Düsseldorf mitgemacht und 3:34h benötigt und hat auch in Dortmund mitgemacht und hat dort 2:40h benötigt. 
Kann ich da mit einer SQL- Abfrage herausbekommen, wie lange Walter Müller z.B.: in Dortmund benötigt hat oder muss ich in der Tabelle "Ergebnisse" noch eine Spalte mit dem Eventnamen hinzufügen?
Besten Dank,
lg


----------



## SlaterB (14. Apr 2011)

da brauchst du die dritte Verknüpfung,
wobei das ganze sinnvoller eh anders aufgebaut wäre:


```
Event: Id, Name, Zeit  ------ Teilnahme/ Ergebnis: EventId, MenschId, Zeit  ------   Mensch: Id, Name, Alter
```

Teilnahme wäre dann exakt die n:m-Beziehnung zwischen Event und Mensch, hier bräuchte es keine zusätzlichen Tabellen


----------



## Generic1 (14. Apr 2011)

OK, stimmt, und ob ein "Mensch" bezahlt hat für einen Event, könnte ich dann auch in die Relationstablelle (Teilnahme) geben, oder wäre das keine gute Idee?

Und eine weitere Info würde mir da einfallen welche ich in die Relationstabelle geben könnte -> der Modus (also 10km, 50km, usw.)?
Dann wäre die Relationstabelle aber ziemlich aufgeblasen, ist das dann noch ok?
lg


----------



## SlaterB (14. Apr 2011)

im Moment klingt es nach einer guten Idee


----------



## Generic1 (14. Apr 2011)

Da kommt mir dann gleich die nächste Frage in den Sinn, kann ich den eine Relationstabelle mit Hibernate erzeugen, welche außer den Relationen noch andere Spalten hat,
In meine jetzigen Applikation (öffensichtlich mit dem falschen DB- Schema) habe ich nur die relationen von 2 Tabellen (bei m:n- Verbindungen).

Ist das überhaupt möglich mit Hibernate?
lg und danke nochmals,


----------



## SlaterB (14. Apr 2011)

ich denke schon dass das möglich ist, allerdings interessiere ich mich überhaupt nicht für automatische Erzeugung oder besonders komplizierte Mappings, kann da nicht weiterhelfen,
bei mir wäre Teilnahme eine komplette eigene Entity mit Java-Klasse, Links auf die anderen beiden Entities


----------



## Generic1 (15. Apr 2011)

Hallo nochmal,

ich habs jetzt versucht, auch so zu machen dass ich eine eigene Entity als Relationstabelle zwischen Event und Participant mache mit dem Namen Participance.
Ich bin mir jetzt aber überhaupt nicht sicher, ob das funktioniert, die Entity- Klasse Event kann jetzt alle zu einem Eventeintrag zugehörigen Participance holen und ein Participant kann auch alle zugehörigen Participance abfragen.
Mir ist jetzt aber nicht klar ob das funktioniert, dass ich zu einem Participant alle zugehörigen Participance und den dazugehörigen Event abfrage kann. Ich hab ja da jetzt eine Beziehung die so ausschaut:


```
Event         1:n               Participance           n:1             Participant
```

also, all Participance für einen Participant und alle Participance für einen Event müsste leicht abzufragen sein, aber den Event für einen Participant mit allen Participance -> geht das dann auch mit HQL?
Vielen Dank,
lg


```
@Entity
@SuppressWarnings("serial")
@Table(name="TEvent")
public class Event implements Serializable {

    private Integer pk_event;
    private String eventname;
    private Timestamp eventtime;
    private int fk_participance;
    private List<Participance> participances;

    public Event() {
        }

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    public Integer getPk_event() {
        return pk_event;
        }

    public void setPk_event(final Integer pk_event) {
        this.pk_event = pk_event;
        }

     /* 1:n relation */
  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)  
  @JoinColumn(name="fk_participance")
  public List<Participance> getParticipance() {
        return participances;
        }

  public void setParticipance(final Participance participance) {
        this.participances.add(participance);
        }

...
```


```
@Entity
@Table(name="TParticipance")
public class Participance implements Serializable {

    private Integer id_participance;

// ab da ist diese Entity eine POJO ohne Annotations
```


```
@Entity
@SuppressWarnings("serial")
@Table(name="TParticipant")
public class Participant implements Serializable {

  private Integer pk_part;
  private String firstname;
  private String surname;
  private int fk_participance;
  private List<Participance> participances;
  
  public Participant() {
    }

  @Id
  @GeneratedValue(generator="foreign")
  @GenericGenerator(name="foreign", strategy = "foreign", parameters={
        @Parameter(name="property", value="contact")
        })
  public Integer getPk_part() {
        return pk_part;
        }

  public void setPk_part(final Integer pk_part) {
        this.pk_part = pk_part;
        }

  /* 1:n relation */
  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)  
  @JoinColumn(name="fk_participance")
  public List<Participance> getParticipance() {
        return participances;
        }

  public void setParticipance(final Participance participance) {
        this.participances.add(participance);
        }
```


----------



## SlaterB (15. Apr 2011)

im Zweifel geht in HQL immer der ganz normale Join, 
statt Ids kann man dann Objekte verwenden bzw. muss wenn die Ids nicht extra gemappt sind


```
from Event e,  Participance c, Participant p
where c in e.participances and c in p.participances
```
müsste gehen, bzw. besser

```
from Event e,  Participance c, Participant p
where e = c.event and p = c.participant
```
sofern auch in diese normalere Richtung korrekt gemappt

gibt noch komplizierte Schreibweisen mit INNER JOIN, aber die kenne ich selber nicht wirklich
und hab eigentlich schon mehr erzählt als durch Lernen zu lernen wäre


----------



## Generic1 (15. Apr 2011)

Hallo,

eine letzte Frage hätte ich noch zu diesem Thema, erscheint das für dich logisch bzw. würdest du das auch so machen, dass ein "Participant" eine @OneToMany- Relation zu "Participance" und das "Event" auch eine @OneToMany- Relation zu "Participance" hat?

Ich frag mich nämlich gerade, wie ich einen Participant für einen Event speichere (über die Tabelle Participance). Also mir ginge es nur mehr um die Vorgehensweise, wie z.B.:

1. schaun obs den Event, für den sich der Participant registrieren will, schon gibt.
2. wenn ja, dann das Event- Objekt holen
3. Participance- Objekt eintragen
4. Participance- Objekt in Event- Objekt setzen
5. Participant in Tabelle eintragen (sollte es den noch nicht geben, ansonsten dieses Participant- Objekt holen)
6. Participance- Objekt in Participant- Objekt setzen.

Würde das so Sinn machen oder gäbe es da einen einfacheren/schnelleren/performanteren Weg?
lg


----------



## SlaterB (15. Apr 2011)

mir gefällt die einfache Richtung im Allgemeinen besser: Participance verweist auf exakt ein Event, nicht Event auf eine Liste von Participance, 
so ist es ja auch in der DB abgebildet,
beim Anlegen von Participance nimmt dieses alle Informationen auf, Event muss nicht neu gespeichert werden 
(selbst wenn nur pseudomäßig, die Information aus der Liste dort sowieso im Participance-Fremdschlüssel landet) 

obwohl beides, auch gleichzeitig, möglich ist, Hibernate kann da auch viel tricksen so dass die Gegenrichtung automatisch befüllt wird usw.,

welche der beiden nötig ist oder ob beide zusammen, das kann man logischerweise nicht generell sagen, 
auch deine Anwendung im Speziellen mag ich nicht beurteilen, dass musst du selber wissen,

wenn du einen funktionierenden Weg gefunden hast, dann sei doch soweit zufrieden, es muss nicht gleich optimal werden,
sobald ein anderer Weg begründet besser erscheint, kann man doch umstellen


----------



## Generic1 (15. Apr 2011)

mir gefällt die einfache Richtung im Allgemeinen besser: Participance verweist auf exakt ein Event, nicht Event auf eine Liste von Participance,
so ist es ja auch in der DB abgebildet,

- gefällt mir jetzt auch besser, werds umändern und dann mal schaun obs geht, ich hab ein altes/anderes DB- Schema gehabt und bin jetzt gerade am Refactoring, deshalb so viele Fragen.
Vielen Dank noch mal!!


----------

