2010-10-15 5 views
5

Derzeit funktioniert diese Funktion: Es zeigt für ein bestimmtes Spiel an, wie viele Jobs es gibt.SQL/Doctrine: Links Join Problem

Das Problem: Wenn es keinen Job gibt, erscheint das Spiel nicht auf der Liste.

Wie wird das Spiel angezeigt, auch wenn kein Job angefügt ist?

Dank

public function getWithGames() 
    { 
     $q = $this->createQuery('c') 
      ->leftJoin('c.stJob j') 
      ->where('j.expires_at > ?', date('Y-m-d h:i:s', time())) 
      ->addOrderBy('c.name'); 

     $q->andWhere('j.is_activated = ?', 1); 
     $q->andWhere('j.is_public = ?', 1); 


     return $q->execute(); 
    } 

Antwort

10

Ihre Bedingungen sollte ein Teil der LEFT JOIN ... ON-Klausel sein.

$q = $this->createQuery('c') 
    ->leftJoin('c.stJob j WITH j.expires_at > ? AND j.is_activated = 1 AND j.is_public = 1', date('Y-m-d h:i:s', time())) 
    ->addOrderBy('c.name'); 

Putting Bedingungen in der ON Klausel (in Bezug auf die WHERE gegen) gibt an, dass sie speziell auf die JOIN anzuwenden. Wenn keine Zeilen diese Bedingungen erfüllen, gibt es keinen Join - und genau das wollen Sie in diesem Fall. Setzen Sie sie in die WHERE zeigt an, dass die Ergebnis Zeilen diese Bedingungen erfüllen müssen. Und natürlich, wenn es keine Verbindung gab, können Sie keine Bedingungen über die j Tabelle erfüllen.

+0

ich denke, das ist wirklich egal, da es eine linke Verbindung ist. also egal, wo die Bedingung angewendet wird. aber schau, was er als das Problem definiert. Wenn es keinen Job gibt, ist es nicht aufgeführt. also möchte er einen Join-Wert, wo (die Job-Attribute public und aktiviert sind 1) OR (beide sind NULL) ... (was passiert, wenn es keinen Job gibt). Der letzte Teil ist, was er vergaß –

+3

Es ist immens wichtig. Ein 'OR ... Zeug ist NULL 'ist überhaupt nicht wünschenswert. Der eigentliche Zweck der ON-Klausel besteht darin, dass dies die Bedingungen sind, die zur Herstellung der Verbindung *** verwendet werden. Wenn keine Zeilen diesen Bedingungen entsprechen, gibt es keinen Join - und im Falle eines LINKEN JOIN ist das in Ordnung. Der Versuch, eine ON-Klausel mit manuell geschriebenen Stuff-NULL-Bedingungen nachzuahmen, ist hässlich. Ich hoffe, das ist nicht der Grund für einen Downvote hier. – VoteyDisciple

+0

das ist völlig richtig. Ich habe dir eine positive Bewertung gegeben :) Was ich nicht mochte war, dass es nicht das Problem in seinem Code ist. Das Problem in seinem Code war ein rein semantisches Problem, nicht zu verstehen, was ein linker Join tatsächlich tut. –

1
$q->andWhere('j.is_activated = ?', 1); 
$q->andWhere('j.is_public = ?', 1); 

, wenn es keine Arbeit ist seine is_activated und is_public Feld 1 sein kippe wird es null sein, so dass Sie so etwas wie benötigen: where (j.is_activated = 1 and j.is_activated = 1) or (j.is_activated = IS NULL and j.is_activated IS NULL) ...

ich bin nicht vertraut mit dem, was librar Sie verwenden konstruieren diese Abfrage, aber ich denke, es könnte wie folgt funktionieren:

public function getWithGames() 
    { 
     $q = $this->createQuery('c') 
      ->leftJoin('c.stJob j') 
      ->where('j.expires_at > ?', date('Y-m-d h:i:s', time())) 
      ->addOrderBy('c.name'); 

     $q->andWhere('(j.is_activated = ? AND j.is_public = 1) OR (j.is_activated IS NULL AND j.is_publicIS NULL)', 1); 

     return $q->execute(); 
    } 

dies ist nicht schön ... aber wie gesagt, ich nicht Ihre Bibliothek kennen. Sie könnten wahrscheinlich eine Reihe von Argumenten übergeben oder etwas wie "orWhere ...." tun. blabla ...

die Art, wie es gemacht wird, ist auch ungeschickt und könnte besser gemacht werden. Benutze die Bedingungen direkt um den Join zu etablieren! auf diese Weise vermeidest du, dass du die ganzen Tische kombinierst und anschließend gefiltert wirst ...