costruire una query SQL complessa (o query)
Domanda
Come parte di un'app web più ampia (utilizzando CakePHP), sto mettendo insieme un semplice sistema di blog.Le relazioni sono estremamente semplici:ogni Utente ha un Blog, che ha molte Voci, che hanno molti Commenti.
Un elemento che vorrei incorporare è un elenco di "voci popolari". Le voci popolari sono state definite come quelle con il maggior numero di commenti nell'ultimo mese e alla fine devono essere ordinati dal numero di commenti recenti.
Idealmente, mi piacerebbe che la soluzione rimanesse all'interno dell'apparato di recupero dati del modello di Cake (Model->find()
, ecc.), ma non sono ottimista al riguardo.
Qualcuno ha una soluzione intelligente/elegante?Mi sto preparando per un po' di hacking SQL selvaggio per farlo funzionare...
Soluzione
Eh, stavo per tornare essenzialmente con la stessa risposta (usando Cake's Model::find):
$this->loadModel('Comment');
$this->Comment->find( 'all', array(
'fields' => array('COUNT(Comment.id) AS popularCount'),
'conditions' => array(
'Comment.created >' => strtotime('-1 month')
),
'group' => 'Comment.blog_post_id',
'order' => 'popularCount DESC',
'contain' => array(
'Entry' => array(
'fields' => array( 'Entry.title' )
)
)
));
Non è perfetto, ma funziona e può essere migliorato.
Ho apportato un ulteriore miglioramento, utilizzando il comportamento Containable per estrarre i dati di ingresso invece dei dati di commento.
Altri suggerimenti
Non dovrebbe essere poi così male, hai solo bisogno di un gruppo di (questo è fuori dal mio genere, quindi perdona gli errori di sintassi):
SELECT entry-id, count(id) AS c
FROM comment
WHERE comment.createdate >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY entry-id
ORDER BY c DESC
Se non ti preoccupi della natura temporale dei commenti, potresti utilizzare la funzionalità counterCache di CakePHP aggiungendo un campo "comment_count" alla tabella delle voci, configurando la chiave counterCache dell'associazione Comment awareTo Entry con questo campo, quindi chiamare find() sul modello Entry.
Probabilmente vuoi un DOVE clausola per ricevere solo i commenti degli ultimi 30 giorni:
SELECT entry-id, count(id) AS c
FROM comment
WHERE comment_date + 30 >= sysdate
GROUP BY entry-id
ORDER BY c DESC