Mentre SQL è abbastanza semplice quando si tratta di rispondere a domande come "quando era il post più recente per ogni giorno?" NON è molto semplice quando chiedi "quale era il post più recente per ogni giorno?"
Non è possibile recuperare l'ultimo post per ogni giorno senza utilizzare un sub SELECT (o più istruzioni SQL). Questo potrebbe funzionare per voi (uso Post.find_by_sql o simile):
SELECT P.*, M.just_day, M.max_created_at
FROM posts P
JOIN (
SELECT date(P2.date) AS just_day, MAX(P2.created_at) AS max_created_at
FROM posts P2
P.location_id='12345' AND P.published=true
GROUP BY date(P2.date)
) AS M
ON AND M.max_created_at = P.created_at
WHERE P.location_id='12345' AND P.published=true
L'istruzione SQL di cui sopra dovrebbe essere abbastanza se si può essere certi che due posti non avranno lo stesso valore nella colonna created_at. Se non è possibile garantire univocità nella colonna creata in, allora è necessario filtrare i duplicati in Ruby (che non dovrebbe essere troppo inefficiente perché presumibilmente si andrà a scorrere sull'elenco in ogni caso) o sarà necessario fare N +1 istruzioni SQL. (In realtà si potrebbe fare selezioni per riga, ma AFAIK è altrettanto inefficiente delle istruzioni SQL N + 1.)
Ecco come si potrebbe rimuovere i duplicati mentre loop:
last_post = nil
posts.each do |post|
unless post.just_day == last_past.try(:just_day)
# Do stuff
last_post = post
end
end
Detto questo, si potrebbe scrivere bene con solo Rubino/ActiveRecord, se avete qualche giorno a sufficienza che un prescelto per ogni isn giorno' t troppo male:
days = Post.group("date(date)")
posts = days.each { |day| Post.order('created DESC').where("date(day) = ?", day) }
Se si utilizza l'impaginazione (dicono 10 articoli per pagina), allora questo richiederà 11 istruzioni SQL per ogni pagina. Non idee, ma la semplicità potrebbe valere l'inefficienza.
Onestamente, se si prevede che questa query sia eseguita frequentemente e con un set di dati ragionevolmente grande, suggerisco di aggiungere una colonna booleana chiamata most_recent. L'ultimo post dei giorni passati non cambierà. Devi solo preoccuparti dei post di oggi. Basta impostare un processo cron per eseguire alcuni minuti dopo la fine della giornata per aggiornare il valore per l'ultimo giorno. Se si desidera qualcosa di più aggiornato, è possibile che il processo cron venga eseguito ogni 5 minuti. Oppure se hai bisogno di tempo reale, quindi aggiungi un callback after_save per impostare most_recent su false per tutti i post di oggi che non sono il post corrente.
Questa domanda è simile: MySQL: Getting highest score for a user
un "allineamento ... raggruppati per data" - questo non ha senso. Cosa stai cercando di ottenere? Puoi semplicemente ordinare per data (data)? – DanSingerman
Qualsiasi database, ad eccezione di MySQL, rifiuterà l'SQL illegale. I database non indovinano quali risultati vorresti oggi, db's dovrebbe ottenere tutti i risultati corretti in tutte le situazioni. Usa ONLY_FULL_GROUP_BY in MySQL e anche la query sopra verrà respinta da MySQL. –
Ciao Dan - Sto cercando di ottenere una serie di oggetti Post ma voglio solo recuperare un Post per un dato giorno (l'ultimo Post per quel giorno). – digitalfrost