Forum: Italian Ruby user group find sul risultato di find. Possibile ?

Posted by Ale Ds (alexdesi)
on 2010-02-24 13:08
Ciao a tutti,

devo eseguire 2 find su un model, dove la seconda find genera un
sottoinsieme dei dati della prima, ad esempio:

a = User.find(:all, :conditions => "age > 18 ")
b = User.find(:all, :conditions => "age > 21 ")

vorrei evitare di rifare la query su tutti gli utenti, ma solo su quelli
di eta>18, l'ideale sarebbe eseguire
a.find(:all, :conditions => "age > 21 ")

ma a e' un array e quindi nn prevede la find.
Cosa faccio:
1) mi rassegno e faccio 2 query
2) filtro l'array a con un ciclo

esiste un'altra immediata soluzione ?

grazie a tutti,
Ale
Posted by Luca De Marinis (Guest)
on 2010-02-24 13:38
(Received via mailing list)
2010/2/24 Ale Ds <alexdesi@gmail.com>

> a.find(:all, :conditions => "age > 21 ")
>
> ma a e' un array e quindi nn prevede la find.
> Cosa faccio:
> 1) mi rassegno e faccio 2 query
> 2) filtro l'array a con un ciclo
>
> esiste un'altra immediata soluzione ?
>


Potresti passare alla seconda query gli id dei record trovati nella 
prima,
tipo

User.find(:all, :conditions => ["age > 21 && id IN (?)", 
primi.map(&:id)])

(e poi verificare se e' davvero piu' veloce che non rifare la query con 
le
due condizioni sulla data, cosa di cui non sono sicuro!).

Ciao
Posted by Pietro Giorgianni (giorgian)
on 2010-02-24 13:53
(Received via mailing list)
Il 24 febbraio 2010 13.38, Luca De Marinis <loop@interact.it> ha 
scritto:
> 2010/2/24 Ale Ds <alexdesi@gmail.com>
>
> Potresti passare alla seconda query gli id dei record trovati nella prima,
> tipo
>
> User.find(:all, :conditions => ["age > 21 && id IN (?)", primi.map(&:id)])
>
> (e poi verificare se e' davvero piu' veloce che non rifare la query con le
> due condizioni sulla data, cosa di cui non sono sicuro!).

Uhm... a occhio, per essere realmente più veloce, la prima query
dovrebbe restituire pochissimi risultati da una tabella immensa.

Un'idea un po' azzardata (sintassi mysql, ma dovrebbe funzionare anche
con altri dbms):

a = User.find_by_sql ["SELECT *, (age > ?) as overage FROM users WHERE
age > ?", 21, 18]
b = a.select {|x| x.overage == "1"}


pietro
Posted by Luca Mearelli (Guest)
on 2010-02-24 17:23
(Received via mailing list)
hmm... rischio di essere pedante :) ma:

2010/2/24 Ale Ds <alexdesi@gmail.com>:
> a = User.find(:all, :conditions => "age > 18 ")
> b = User.find(:all, :conditions => "age > 21 ")

forse, cercando una risposta, dovresti chiarirti alcune cose

- ti servono entrambe le liste di utenti? e ti serve che siano distinte?
- devi fare qualcosa di particolare con gli utenti della lista a che
non sono nella lista b?

nota che: b e' un sottinsieme proprio di a

quindi estraendo i dati con la prima query hai gia ottenuto anche
tutti gli elementi in b,
dunque non avresti bisogno di fare la seconda query, se comunque devi
processare tutti gli elementi in a.

qualcosa di simile a quello che cerchi lo potresti ottenere usando dei
named_scope, ma se lo facessi, viste le condizioni nei due casi,
otteresti una query tipo questa:

select * from users where age > 18 and age > 21

che e' equivalente a:

select * from users where age > 21

Altrimenti se proprio hai bisogno dei due insiemi di utenti, potresti
fare deu query che estraggono i dati dei due sottoinsiemi disgiunti:

c = User.find(:all, :conditions => "age > 18 AND age <= 21")
b = User.find(:all, :conditions => "age > 21 ")

N.B. c = a-b

ciao,
Luca
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.