2010-10-15 18 views
5

Actualmente esta función funciona: se muestra para un juego específico, cuántos trabajos hay.SQL/Doctrine: Problema de unión izquierda

El problema: si no hay trabajo, el juego no aparece en la lista.

Cómo mostrar el juego incluso si no hay trabajo adjunto?

Gracias

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(); 
    } 

Respuesta

10

Sus condiciones deben ser parte de la combinación izquierda ... cláusula ON.

$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'); 

condiciones de poner en el ON cláusula (en contraposición a la WHERE) indica que se aplican específicamente a la JOIN. Si ninguna fila satisface esas condiciones, no hay unión, y eso es justo lo que quiere en este caso. Ponerlos en el WHERE indica que las filas del resultado deben cumplir esas condiciones. Y, obviamente, si no hubo unión, no puede satisfacer ninguna condiciones sobre la tabla j.

+0

Creo que esto realmente no importa ya que es un complemento de la izquierda. así que no importa dónde se aplica la condición. pero mira lo que él define como el problema. si no hay trabajo, no está en la lista. así que quiere un valor agregado donde (los atributos de trabajo público y activado son 1) O (ambos son NULL) ... (lo que sucede si no hay trabajo). la última parte es lo que olvidó –

+3

Importa muchísimo. Hacer un 'O ... cosas es NULL' no es para nada deseable. El propósito de la cláusula 'ON 'es que esas son las condiciones *** usadas para establecer el join ***. Si ninguna fila coincide con esas condiciones, no hay unión, y en el caso de una unión IZQUIERDA, está bien. Tratar de imitar una cláusula 'ON 'con condiciones" NULL "escritas manualmente es feo. Espero que esa no sea la razón de un voto negativo aquí. – VoteyDisciple

+0

eso es totalmente cierto. te di un voto positivo por esto :) lo que no me gustó fue que no es el problema en su código. el problema en su código era un problema puramente semántico de no entender lo que hace realmente una combinación de la izquierda. –

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

si no hay trabajo y su is_activated campo is_public no puede ser 1. será nula por lo que necesita algo como: where (j.is_activated = 1 and j.is_activated = 1) or (j.is_activated = IS NULL and j.is_activated IS NULL) ...

no estoy familiarizado con lo que librar que está utilizando para la construcción de esta consulta, pero supongo que podría funcionar así:

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(); 
    } 

esto no es bastante ... pero como ya he dicho que no sé su biblioteca. probablemente podría pasar una serie de argumentos o hacer algo como "orWhere ...." blabla ...

la forma en que se hace es también torpe y podría hacerse mejor. usa las condiciones directamente para establecer la unión! de esa manera evitas ahving todas las tablas combinadas y luego filtradas ...

Cuestiones relacionadas