Forum: Rails-ES SQL GROUP BY

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Rafa C. (Guest)
on 2009-03-26 11:59
Tengo definida una tabla son la siguiente estructura:

table: diario
cuenta string(10)
debe   numeric
haber  numeric
...

Estoy probando de ejecutar una consulta SQL que haga un SUM y un GROUP
BY

SELECT cuenta, sum(debe) sumdebe, sum(haber) sumhaber from diario group
by cuenta


Para ejecutar este SQL he escrito el siguiente codigo:

@cuentas=diario.find_by_sql("SELECT cuenta, sum(debe) sumdebe,
sum(haber) sumhaber from diario group by cuenta")

y he visto que el resultado de la SQL se mapea sobre la definicion de la
tabla. Es decir, solo me devuelve la columna cuenta.

En cambio si ejecuto:
@cuentas=diario.find_by_sql("SELECT cuenta, sum(debe) debe, sum(haber)
haber from diario group by cuenta")
me devuelve las 3 columnas.

A raiz de este problema, se me han planteado 2 preguntas:
a) Como se puede hacer SQL libres sin pasar por el mapping del modelo?
b) Como es posible saber el nombre de las columnas que han retornado un
SQL?

Gracias
Emili P. (Guest)
on 2009-03-26 12:27
(Received via mailing list)
Hola Rafa ;)


> A raiz de este problema, se me han planteado 2 preguntas:
> a) Como se puede hacer SQL libres sin pasar por el mapping del modelo?

Cundo haces un find_by_sql se ejecuta la sentencia SQL directamente, con
lo
cual al mapping del modelo no deberia afectarte

>
> b) Como es posible saber el nombre de las columnas que han retornado un
> SQL?

El resultado de un find es un array de objetos, si lo recorres puedes
hacer
un respond_to? para ver si existe ese atributo

@cuentas.each do |cuenta|
if cuenta.respond_to? :sumdebe
...
end
end
Rafa C. (Guest)
on 2009-03-26 13:02
Hola Emili, que ilusion de ver tus respuestas!!!. Ha sido una gran
alegria y sorpresa!!!


En cuanto al tema que nos ocupa:

A) He ejecutado las siguientes instrucciones desde la consola y el
resultado es el siguiente:

>> @comptes2=Diario.find_by_sql("SELECT cuenta, sum(debe) debe from diario where cuenta = 
'430017' group by cuenta")
=> [#<Diario cuenta: "430017", debe:
#<BigDecimal:b6ed67bc,'0.195E4',4(12)>>]

>> @comptes2=Diario.find_by_sql("SELECT cuenta, sum(debe) sumdebe from diario where cuenta 
= '430017' group by cuenta")
=> [#<Diario cuenta: "430017">]

No veo que aparezca sumdebe en el retorno de la segunda consulta.Yo creo
que esta mapeando con el modelo.


B) Como es posible saber el nombre de las columnas que han retornado un
SQL?
Estoy probando de hacer una unica view que pueda pintar los resultados
de diferentes consultas SQL. Para ello, puedo montar dinamicamente el
string SQL (en funcion de los datos que el usuario necesite) y
ejecutarlo, pero necesitaria saber que columnas me devuelven. A priori,
no se como se llaman las columnas, por tanto no puedo utilizar el metodo
respond_to?.
Hay algun array que me indique los atributos de las columnas de una
query?


> Hola Rafa ;)
>
>
>> A raiz de este problema, se me han planteado 2 preguntas:
>> a) Como se puede hacer SQL libres sin pasar por el mapping del modelo?
>
> Cundo haces un find_by_sql se ejecuta la sentencia SQL directamente, con
> lo
> cual al mapping del modelo no deberia afectarte
>
>>
>> b) Como es posible saber el nombre de las columnas que han retornado un
>> SQL?
>
> El resultado de un find es un array de objetos, si lo recorres puedes
> hacer
> un respond_to? para ver si existe ese atributo
>
> @cuentas.each do |cuenta|
> if cuenta.respond_to? :sumdebe
> ...
> end
> end
LLeïr Borràs (Guest)
on 2009-03-26 13:16
(Received via mailing list)
2009/3/26 Rafa C. <removed_email_address@domain.invalid>:
> => [#<Diario cuenta: "430017", debe:
> #<BigDecimal:b6ed67bc,'0.195E4',4(12)>>]
>
>>> @comptes2=Diario.find_by_sql("SELECT cuenta, sum(debe) sumdebe from diario where 
cuenta = '430017' group by cuenta")
> => [#<Diario cuenta: "430017">]
>
> No veo que aparezca sumdebe en el retorno de la segunda consulta.Yo creo
> que esta mapeando con el modelo.

Ahun que no aparezca el nombre en el retorno no quiere decir que no
puedas acceder al resultado. Puedes evaluar el valor de
@comptes2.first.sumdebe o @comptes2.first['sumdebe'] para ver si tiene
valor, pero diria que mejor mires activerecord como hacer esta misma
consulta si utilizar un find_by_sql...

>
>
> B) Como es posible saber el nombre de las columnas que han retornado un
> SQL?

@comptes2.count

> Estoy probando de hacer una unica view que pueda pintar los resultados
> de diferentes consultas SQL. Para ello, puedo montar dinamicamente el
> string SQL (en funcion de los datos que el usuario necesite) y
> ejecutarlo, pero necesitaria saber que columnas me devuelven. A priori,
> no se como se llaman las columnas, por tanto no puedo utilizar el metodo
> respond_to?.
> Hay algun array que me indique los atributos de las columnas de una
> query?

Utiliza los hacks que no da activerecord en vez de find_by_sql pelado
Emili P. (Guest)
on 2009-03-26 13:22
(Received via mailing list)
2009/3/26 Rafa C. <removed_email_address@domain.invalid>

> where cuenta = '430017' group by cuenta")
> => [#<Diario cuenta: "430017", debe:
> #<BigDecimal:b6ed67bc,'0.195E4',4(12)>>]
>
> >> @comptes2=Diario.find_by_sql("SELECT cuenta, sum(debe) sumdebe from
> diario where cuenta = '430017' group by cuenta")
> => [#<Diario cuenta: "430017">]
>
> No veo que aparezca sumdebe en el retorno de la segunda consulta.Yo creo
> que esta mapeando con el modelo.


Segun la documentación [1] el metodo find_by_sql hace

Executes a custom SQL query against your database and returns all the
results. The results will be returned as an array withcolumns requested
encapsulated as attributes of the model you call this method from. If
you
call Product.find_by_sql then the results will be returned in a Product
object with the attributes you specified in the SQL query.

Osea que si mapea el resultado sobre los atributos del Modelo. Tenias
razon.
Puedes probar a crear un accessor a ver si mapea el resultado en él.

class Cuenta < ActiveRecord::Base
  attr_accessor :sumdebe
end



> respond_to?.
> Hay algun array que me indique los atributos de las columnas de una
> query?
>
Sobre un objeto puedes hacer

@cuentas.attribute_names

y te devuelve un array con todos los atributos del modelo.


[1] http://api.rubyonrails.org/classes/ActiveRecord/Ba...
Efrén José Fuentes R. (Guest)
on 2009-03-26 14:35
(Received via mailing list)
Creo que debe ser algo asi:

Diario.sum('debe', :group => 'cuenta')

El 26/03/2009, a las 05:29 a.m., Rafa C.
escribió:
> Tengo definida una tabla son la siguiente estructura:
This topic is locked and can not be replied to.