Pregunta

Quiero mostrar el número de comentarios para cada publicación de blog (junto con la categoría, fecha, autor, etc.) en una página que tiene una lista de publicaciones de blog. ¿Cómo escribo la siguiente consulta mysql en propel?

SELECT post.id, post.title, post.more_columns , COUNT(comments.post_id) AS numofcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id, post.title, post.more_columns

donde post es una tabla de blog y comentarios, una tabla de comentarios con post_id como clave externa para post.id. Parece que no puedo obtener 'numofcomments' como una columna en el conjunto de resultados. Actualmente estoy usando un enfoque que no es ORM (que será mi último recurso):

$con = Propel::getConnection(PostPeer::DATABASE_NAME);

    $sql = "SELECT post.* , COUNT(comments.post_id) AS numcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id";  
    $stmt = $con->prepare($sql);
    $stmt->execute();

    $result = PostPeer::populateObjects($stmt);
    return $result;

¿Cómo puedo acceder a 'numofcomments' en el conjunto de resultados de Propel resultante?

EDITAR: ¿Lo que quería saber es cómo puedo escribir la consulta anterior en Propel? Lo que puedo hacer ahora es obtener la tabla de publicación con unión interna en la tabla de comentarios y luego ejecutar doCount en la tabla de comentarios para cada ID de publicación. Esto da como resultado 1 consulta para la tabla Publicar y muchas consultas para la tabla de comentarios. Deseo reducir las consultas sql al mínimo. Gracias :)

¿Fue útil?

Solución 4

Bueno, esto es lo que funcionó, pero es una forma triste de hacerlo: |

//inside a static function in class PostPeer:
$c = new Criteria();
self::addSelectColumns($c); //add all columns from PostPeer
$c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
$cu->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
$cu->addGroupByColumn(PostPeer::ID);
$cu->addGroupByColumn(PostPeer::TITLE);
:
:
//more group-by columns if needed
return PostPeer::doSelectStmt($c);

Luego, en la plantilla, accedo a la matriz como:

<div id="title">
   <?php echo post_array[1] ?>
</div>
//...and so on for other Post fields

¿Cómo hago una asociación de matriz en el modelo para poder escribir " post_array ['title'] " en la plantilla en lugar de " post_array [1] " ;? Además, ¿es segura esta solución? Cualquier sugerencia mejor. Estoy usando Propel 1.3

Otros consejos

SELECCIONE post. *, COUNT (comments.post_id) AS numcomments FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id, post.secondcol, post.thirdcol; y así sucesivamente, solo enumere todas las columnas individuales en su tabla de publicaciones, ya que selecciona publicar. *, debe enumerarlas todas, no solo post.post_id.

Alternativamente

SELECT post.*,sub.numcomments from post,
(select post.post_id as post_id,COUNT(comments.post_id) AS numcomments 
   FROM post INNER JOIN comments ON post.id = comments.post_id GROUP BY post.id) as sub
   where post.post_id = sub.post_id;

(También hay una forma 3. y más fácil, que olvidé ahora ...)

Si desea incluir datos adicionales en sus objetos devueltos por una consulta personalizada, puede anular el método doSelect () predeterminado en su clase de pares y agregar estos datos adicionales de su consulta en cada objeto que se devuelve.

En su clase de publicaciones, puede agregar una variable protegida, llamémosla "numComments".

class Post extends BasePost {
  protected $numComments;

  public function setNumComments($v)
  {
    $this->numComments = $v;
  }

  public function getNumComments()
  {
    return $this->numComments;
  }
  ...
}

y luego en su clase PostPeer en su método estático doSelectWithCount ():

public static function doSelectWithCount() {
  $c = new Criteria();
  self::addSelectColumns($c); //add all columns from PostPeer
  $c->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
  $c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
  $c->addGroupByColumn(PostPeer::ID);
  $c->addGroupByColumn(PostPeer::TITLE);
  // ...
  // more group-by columns if needed
  $rs = PostPeer::doSelectRS($c);

  $posts = array();
  while ($rs->next()) {
    $post = new Post();
    $post->hydrate($rs);
    $post->setNumComments($rs->getInt(PostPeer::NUM_COLUMNS + 1));
    $posts[] = $post;
  }

  return $posts;
}

Aquí está la versión propel de su consulta SQL.

$c = new Criteria();
// count comments with 
$c->addAsColumn('numofcomments', 'COUNT('.CommentPeer::POST_ID.')');
$c->addJoin(PostPeer::ID, CommentPeer::POST_ID, Criteria::LEFT_JOIN);
$c->addGroupByColumn(PostPeer::ID);
$c->addGroupByColumn(PostPeer::TITLE);
// you can add more groupby column here
//$c->addGroupByColumn(...more);
$this->posts = PostPeer::doSelect($c);

Deberías usar LEFT JOIN en lugar de INNER JOIN. Porque. con la unión interna solo puedes acceder a las publicaciones que tienen al menos un comentario. Con la unión izquierda puedes seleccionar publicaciones sin comentar.

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top