Query SQL, un caso particolare


#1

Ciao,

mi trovo un po nei casini, credo di aver strutturato correttamente il
mio db ma ho dei problemi ad effettuare una query.
In breve ho una table Travels e una Locations e ogni travel ha più locations

il punto è che io quando faccio la query ho le condizioni sulle location
ma voglio prendere i viaggi, mi spiego meglio, la query mi restituisce
tutti i viaggi che hanno le locations filtrate secondo le condizioni ma
il problema è che mi restituisce le sole locations su quelle
condizioni(come giusto che sia alla fine)

@travels = Travel.find(:all,

:include => [:user,:location],

:conditions => [“locations.place = ? OR locations.country_id = ? OR
period = ? OR MONTH(travel_departure) = ?”,
params[:search_item],country_id,params[:search_item],params[:search_item]
])

questa query mi ridà un array di travels ciascuno con le relative
location, il punto è che mi da solo quelle che fanno match con le
conditions mentre io vorrei tutti i viaggi con tutte le location del
viaggio.

Un esempio banale è: cerco un viaggio che contenga il termine “roma” e ho
un viaggio che va da Roma a Madrid, in questo caso la query mi
restituisce si il viaggio ma con la sola location Romal.

La soluzione è banale dovrei fare una query per prendere tutte le
locations che fanno match e da li prendere tutti i relativi travel con
travel_id uguale a quello delle location, in questo modo avrei gli id
dei travel che fanno match e potrei estrarre tutte le reelative
locations.

La domanda è, si può far in modo più intelligente?

Saluti Andrea


#2

Se non ho capito male hai bisogno di aggiungere un’altro join di
travel con location. Nel framework di ruby, questo si dovrebbe
tradurre nel creare un’altra associations, :includerla via eager
loading, richiedere le condizioni su questa seconda associazione,
disambuiguando le condizioni e infine estrarre le locations della
prima associazione.

Se non ti riesce forse ti conviene effettivamente controllare il join
e le join conditions con il parametro :join di #find.

Ciao


#3

Se hai una query complicata, non c’è niente di male nello scrivere

def Travel.find_by_this_and_that
Travel.find_by_sql(“select * from travels where id in (select id from
… )”)
end

piuttosto che incasinarti a cercare i parametri giusti da passare alla
find, scrivi la query sql. Il bello di ActiveRecord è che non ti
nasconde il motore SQL sottostante. Si limita a scrivere per te le
query banali. Le query interessanti puoi benissimo scrivertele a mano
:slight_smile:

M


#4

con l’ sql però ho il problema che non mi restituisce le locations(se non
con query con travel_id duplicati), con la include io mi ritrovo un
array di
oggetti Travel i quali hanno al loro interno un’ array di Location

Capito cosa intendo?

----- Original Message -----
From: “Matteo V.” removed_email_address@domain.invalid
To: “ruby-it” removed_email_address@domain.invalid
Sent: Monday, February 26, 2007 5:46 PM
Subject: Re: [ruby-it] query SQL, un caso particolare

Se hai una query complicata, non c’è niente di male nello scrivere

def Travel.find_by_this_and_that
Travel.find_by_sql(“select * from travels where id in (select id from
… )”)
end

piuttosto che incasinarti a cercare i parametri giusti da passare alla
find, scrivi la query sql. Il bello di ActiveRecord è che non ti
nasconde il motore SQL sottostante. Si limita a scrivere per te le
query banali. Le query interessanti puoi benissimo scrivertele a mano
:slight_smile:

M

On 2/25/07, stb removed_email_address@domain.invalid wrote:

giusto che sia alla fine)
questa query mi ridà un array di travels ciascuno con le relative
travel_id uguale a quello delle location, in questo modo avrei gli id dei
Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


#5

Io ho usato le include per la loro semplicità

ora come ora le uniche due idee sono o fare una query per prendere tutte
le
location e da li prendere tutti i travel_id per fare la seconda query.

Oppure usare la find_by_sql mettendo una select annidata, l’ unico
problema
qui è che non ho la minima idea di come presentare gli oggetti nella
stessa
forma in cui me li presenta rails ovvero un array di oggetti travel con
ciascuno il suo array di oggetti location, la select di solito
restituisce
un join delle table e non mi raggruppa le locations, o almeno io non lo
so
fare, qualcuno ha voglia di darmi una mano?

Saluti Andrea

----- Original Message -----
From: “Matteo V.” removed_email_address@domain.invalid
To: “ruby-it” removed_email_address@domain.invalid
Sent: Tuesday, February 27, 2007 9:04 PM
Subject: Re: [ruby-it] query SQL, un caso particolare

On 2/26/07, stb removed_email_address@domain.invalid wrote:

con l’ sql però ho il problema che non mi restituisce le locations(se non
con query con travel_id duplicati), con la include io mi ritrovo un array
di
oggetti Travel i quali hanno al loro interno un’ array di Location

Capito cosa intendo?

Sì.
Ti consiglio di scrivere un test che verifica che riesci a estrarre le
informazioni che ti interessano in maniera corretta, evitando
all’inizio di incasinarti con :include. All’inizio la cosa più
importante è ottenere le informazioni, non farlo in maniera
efficiente.

Una volta che hai il test che ti protegge, puoi provare a sperimentare
con :include per verificare se riesci a evitare di fare N+1 query.

Io farei così :slight_smile:

M

def Travel.find_by_this_and_that
M

ma voglio prendere i viaggi, mi spiego meglio, la query mi restituisce
:conditions => ["locations.place = ? OR locations.country_id = ? OR
Un esempio banale è: cerco un viaggio che contenga il termine “roma” e

http://lists.ruby-it.org/mailman/listinfo/ml


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


#6

On 2/28/07, stb removed_email_address@domain.invalid wrote:

Io ho usato le include per la loro semplicità

ora come ora le uniche due idee sono o fare una query per prendere tutte le
location e da li prendere tutti i travel_id per fare la seconda query.

Sembra una buona idea. Così fai solo due query. Il tempo di ordinare
in memoria gli oggetti dovrebbe essere minimo, se non sono migliaia.

M


#7

On 2/26/07, stb removed_email_address@domain.invalid wrote:

con l’ sql però ho il problema che non mi restituisce le locations(se non
con query con travel_id duplicati), con la include io mi ritrovo un array di
oggetti Travel i quali hanno al loro interno un’ array di Location

Capito cosa intendo?

Sì.
Ti consiglio di scrivere un test che verifica che riesci a estrarre le
informazioni che ti interessano in maniera corretta, evitando
all’inizio di incasinarti con :include. All’inizio la cosa più
importante è ottenere le informazioni, non farlo in maniera
efficiente.

Una volta che hai il test che ti protegge, puoi provare a sperimentare
con :include per verificare se riesci a evitare di fare N+1 query.

Io farei così :slight_smile:

M


#8

già alla fine o faccio così o non so come venirne fuori, grazio dell’ aiuto
:]

Salut Andrea

----- Original Message -----
From: “Matteo V.” removed_email_address@domain.invalid
To: “ruby-it” removed_email_address@domain.invalid
Sent: Wednesday, February 28, 2007 11:26 PM
Subject: Re: [ruby-it] query SQL, un caso particolare

On 2/28/07, stb removed_email_address@domain.invalid wrote:

Io ho usato le include per la loro semplicità

ora come ora le uniche due idee sono o fare una query per prendere tutte
le
location e da li prendere tutti i travel_id per fare la seconda query.

Sembra una buona idea. Così fai solo due query. Il tempo di ordinare
in memoria gli oggetti dovrebbe essere minimo, se non sono migliaia.

M


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


#9

allora ho fatto due query ma la seconda mi ritorna un errore di sintassi
sql
e non ne riesco proprio a capire il motivo.
ho provato sia a mettere parentesi sia a fare la query tipo travel_id IN
222
(con un solid id) e non va, stesso errore di sintassi, cosa sto
sbagliando?

questà è la query
locations = Location.find(:all,

:conditions => [“locations.place = ? OR locations.country_id = ?”,
params[:search_item],country_id])

@travels = Travel.find(:all,

:include => [:user,:location],

:conditions => [“travel_id IN ?”,locations.map{|e| e.travel_id} ])

e questo è l’ errore

Mysql::Error: #42000Errore di sintassi nella query SQL vicino a ‘222)’
linea
1: SELECT travels.id AS t0_r0, travels.user_id AS t0_r1,
travels.description AS t0_r2, travels.name AS t0_r3,
travels.goal_id
AS t0_r4, travels.transport_id AS t0_r5, travels.total_places AS
t0_r6,
travels.created AS t0_r7, travels.period AS t0_r8,
travels.travel_departure AS t0_r9, travels.travel_return AS t0_r10,
users.id AS t1_r0, users.login AS t1_r1, users.email AS t1_r2,
users.crypted_password AS t1_r3, users.salt AS t1_r4,
users.created_at
AS t1_r5, users.updated_at AS t1_r6, users.remember_token AS t1_r7,
users.remember_token_expires_at AS t1_r8, users.name AS t1_r9,
users.surname AS t1_r10, users.city AS t1_r11, users.country_id AS
t1_r12, users.photo AS t1_r13, users.birthday AS t1_r14,
users.language AS t1_r15, users.latitude AS t1_r16,
users.longitude AS
t1_r17, users.gender AS t1_r18, users.about AS t1_r19,
users.photo_miniature AS t1_r20, users.photo_thumbnail AS t1_r21,
locations.id AS t2_r0, locations.travel_id AS t2_r1,
locations.place
AS t2_r2, locations.country_id AS t2_r3, locations.latitude AS
t2_r4,
locations.longitude AS t2_r5, locations.accuracy AS t2_r6,
locations.departure AS t2_r7, locations.seq AS t2_r8 FROM travels
LEFT
OUTER JOIN users ON users.id = travels.user_id LEFT OUTER JOIN
locations ON
locations.travel_id = travels.id WHERE (travel_id IN 222) ----- Original
Message -----
From: “stb” removed_email_address@domain.invalid
To: “ruby-it” removed_email_address@domain.invalid
Sent: Wednesday, February 28, 2007 11:54 PM
Subject: Re: [ruby-it] query SQL, un caso particolare


#10

Ciao Stb,
non conosco ancora ruby… per ora sono un mero lurker (si dice così?)
di
questa lista… ma credo che il tuo problema sia nella formulazione
della
query:

locations = Location.find(:all,

:conditions => [“locations.place = ? OR locations.country_id = ?”,
params[:search_item],country_id])
@travels = Travel.find(:all,
:include => [:user,:location],
:conditions => [“travel_id IN ( ? )”,locations.map{|e| e.travel_id} ])

nota le ( ) dopo IN.

Credo che così ti debba andare…
…da quello che si intuisce nell’errore è proprio questo.

Ciao.
Diego

P.S. Bel lavoro Ptumpa ho avuto modo di dargli uno sguardo durante il
Barcamp di Roma :wink:

On 01/03/07, stb removed_email_address@domain.invalid wrote:

locations = Location.find(:all,
e questo è l’ errore
users.crypted_password AS t1_r3, users.salt AS t1_r4,
AS t2_r2, locations.country_id AS t2_r3, locations.latitude AS t2_r4,
Subject: Re: [ruby-it] query SQL, un caso particolare

Sent: Wednesday, February 28, 2007 11:26 PM
Sembra una buona idea. Così fai solo due query. Il tempo di ordinare
http://lists.ruby-it.org/mailman/listinfo/ml


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


Diego La Monica
Analista programmatore
Programmazione, Standards ed Accessibilità
Membro: IWA Italy
Via Napoli, 5 - Loc. la Scala
56028 San Miniato (PISA)

tel. (+39) 0571464992
cell. (+39) 3337235382
e-mail: removed_email_address@domain.invalid
skype: diego.la.monica
ICQ #: 249-460-264
web: http://dlamonica.netsons.org


#11

stb wrote:

@travels = Travel.find(:all,

:include => [:user,:location],

:conditions => [“travel_id IN ?”,locations.map{|e| e.travel_id} ])

di getto direi:

:conditions => [“travel_id IN (?)”,locations.map{|e|
e.travel_id}.join(’,’) ])

La ‘IN’ e’ “travel_id IN (100, 101, 102)”

ciao
Luca

Web: http://spazidigitali.com - http://thetyper.com
Email mailto://removed_email_address@domain.invalid
Skype callto://l.mearelli


#12

grazie mille era proprio questo, è che le parentesi le avevo provate a
mettere nel poso sbagliato :]

Saluti Andrea

----- Original Message -----
From: “Diego La Monica” removed_email_address@domain.invalid
To: “ruby-it” removed_email_address@domain.invalid
Sent: Thursday, March 01, 2007 4:57 PM
Subject: Re: [ruby-it] query SQL, un caso particolare

Ciao Stb,
non conosco ancora ruby… per ora sono un mero lurker (si dice così?)
di
questa lista… ma credo che il tuo problema sia nella formulazione
della
query:

locations = Location.find(:all,

:conditions => [“locations.place = ? OR locations.country_id = ?”,
params[:search_item],country_id])
@travels = Travel.find(:all,
:include => [:user,:location],
:conditions => [“travel_id IN ( ? )”,locations.map{|e| e.travel_id} ])

nota le ( ) dopo IN.

Credo che così ti debba andare…
…da quello che si intuisce nell’errore è proprio questo.

Ciao.
Diego

P.S. Bel lavoro Ptumpa ho avuto modo di dargli uno sguardo durante il
Barcamp di Roma :wink:

On 01/03/07, stb removed_email_address@domain.invalid wrote:

locations = Location.find(:all,
e questo è l’ errore
users.crypted_password AS t1_r3, users.salt AS t1_r4,
AS t2_r2, locations.country_id AS t2_r3, locations.latitude AS t2_r4,
Subject: Re: [ruby-it] query SQL, un caso particolare

Sent: Wednesday, February 28, 2007 11:26 PM
Sembra una buona idea. Così fai solo due query. Il tempo di ordinare
http://lists.ruby-it.org/mailman/listinfo/ml


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml


Diego La Monica
Analista programmatore
Programmazione, Standards ed Accessibilità
Membro: IWA Italy
Via Napoli, 5 - Loc. la Scala
56028 San Miniato (PISA)

tel. (+39) 0571464992
cell. (+39) 3337235382
e-mail: removed_email_address@domain.invalid
skype: diego.la.monica
ICQ #: 249-460-264
web: http://dlamonica.netsons.org


Ml mailing list
removed_email_address@domain.invalid
http://lists.ruby-it.org/mailman/listinfo/ml