¿Select con join?

Hola a todos,
tengo una tabla products donde guardo:

id name price
1 a 2
2 a 10
3 b 5
4 c 3
5 c 5

Necesito montar un select que me devuelva para un mismo producto, el
precio más bajo, en este ejemplo sería:

id name price
1 a 2
3 b 5
4 c 3

Muchas gracias.

2008/9/18 Pepe B. [email protected]

Hola a todos,

Hola

1 a 2
3 b 5
4 c 3
Muchas gracias.

Eso mejor que preguntes en foros/listas de sql. Esta lista es de rails,
y no
se que tiene que ver lo que preguntas con rails.
De todas formas un
“select name, id, MINIMUN (price) from products group by name,id order
by
name ASC”
o algo parecido te podría funcionar.

Un Saludo

Product.minimum(:price, :group => :name)

2008/9/18 Guillermo [email protected]:

1 a 2
Muchas gracias.


Guillermo Álvarez


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Lucas F.
Developer

Personal: http://www.lucasefe.com.ar/
Development: http://drivendevelopment.com.ar/

En SQL sería:

SELECT products.name, products.price from products inner join (
SELECT name, min(price) as mp from products group by name) as x
ON products.name=name AND products.price=mp

2008/9/18 Pepe B. [email protected]:

Necesito montar un select que me devuelva para un mismo producto, el


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es

Hola,

Mírate la opción :group de ActiveRecord::Base#find
(http://apidock.com/rails/ActiveRecord/Base/find/class).

Pero creo que antes de nada deberías asegurarte de saber hacerlo con SQL.

Un saludo,


Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras

2008/9/18 Lucas F. [email protected]:

Product.minimum(:price, :group => :name)

Brillante!, no sabía que las calculations aceptaran :group


Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras

Hola,
he probado lo del minimum, creo que servirá, pero me falla un detalle:

[[2, “a”], [5, “b”], [3, “c”]

Pero necesito también que devuelva el id del producto más bajo.
He intentado incluir :select => :id, pero devuelve un id que no toca en
algunos casos, creo que devuelve el primero que pilla y no coincide
realmente con el id del producto de menor precio.

On Fri, Sep 19, 2008 at 10:01 AM, Pepe B. <
[email protected]> wrote:

En SQL sería:

SELECT products.name, products.price from products inner join (
SELECT name, min(price) as mp from products group by name) as x
ON products.name=name AND products.price=mp

En todo caso no seria:

ON products.name = x.name AND products.price = x.mp

?

Bueno igual ya con lo del minimun ya resuelves.

Saludos!

Es magia! :wink:

On Thu, Sep 18, 2008 at 11:18, Sergio Gil Pérez de la Manga
[email protected] wrote:

now > http://twitter.com/porras


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Lucas F.
Developer

Personal: http://www.lucasefe.com.ar/
Development: http://drivendevelopment.com.ar/

Lucas F. wrote:

Es magia! :wink:

¿Perdona?

2008/9/18 Pepe B. [email protected]:

Hola,
he probado lo del minimum, creo que servirá, pero me falla un detalle:

[[2, “a”], [5, “b”], [3, “c”]

Pero necesito también que devuelva el id del producto más bajo.
He intentado incluir :select => :id, pero devuelve un id que no toca en
algunos casos, creo que devuelve el primero que pilla y no coincide
realmente con el id del producto de menor precio.

Si necesitas el objeto de verdad, tendrás que usar find. Yo creo que
algo así o muy parecido
funcionará:
Product.find(:all, :group => :name, :select => “id, name, MIN(price) as
price”)

Si necesitas más cosas aparte del id y el nombre tendrás que ponerlas también.


Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras

On Thu, Sep 18, 2008 at 4:22 PM, Lucas F. [email protected]
wrote:

Es magia! :wink:

Pero cuidado! (lo acabo de probar por curiosidad).

minimum no te devuelve los modelos, sólo el valor de ese minimo, y el
valor por el que agrupas, en un array anidado. En el caso de nuestro
amigo Pepe, algo
así:
[[a, 2], [b, 5], [c, 3]]

Si no te basta con eso y necesitas el objeto completo, has de
encargarte de tratar el array y cargar los objetos de la base de
datos. Y en ese caso quizás compensaría hacerlo directamente con un
find con :group

En cualquier caso, muy buen truco.


Sergio Gil Pérez de la Manga
e-mail > [email protected]
blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras

Sergio Gil Pérez de la Manga wrote:

funcionar�:
Product.find(:all, :group => :name, :select => “id, name, MIN(price) as
price”)

Gracias Sergio,
la consulta me la devuelve bien, el nombre el que toca, el precio mínimo
también, pero como antes, el ID no corresponde con ese producto.

1 a 10
2 a 2

Imagina que tendría que darme

2 a 2

Me devuelve:

1 a 2

Devuelve el primer ID del producto con name = a

Correcto Sergio.

Sobre tu respuesta del find, hemos posteado al mismo tiempo y no se si
la habrás leido ¿es normal lo que te comento de que devuelve el primer
ID que pilla?

Muchísimas gracias por tu ayuda, se agradece mucho.

Tenés razón, no me fijé eso. Bien notado. :slight_smile:

On Thu, Sep 18, 2008 at 11:33, Sergio Gil Pérez de la Manga
[email protected] wrote:

blog > http://www.lacoctelera.com/porras
now > http://twitter.com/porras


Ror-es mailing list
[email protected]
http://lists.simplelogica.net/mailman/listinfo/ror-es


Lucas F.
Developer

Personal: http://www.lucasefe.com.ar/
Development: http://drivendevelopment.com.ar/

Pepe,

es un tema de MySQL, no de Rails o Ruby.

Te recomiendo que te mires los manuales de MySQL, pero lo que sí te
puedo decir es que es NORMAL. Cuando haces una operación de agrupación
(MINIMUM en este caso) y lo mezclas con valores no agregados (id en tu
caso) los resultados son “impredecibles”, y de hecho en otras bases de
datos SQL directamente no te deja ejecutar estas SQL (Me viene a la
cabeza informix).

Lo dicho, mirate los manuales de MySQL para ver como puedes ejecutar
esto en una sola SQL o si debes ejecutar una para cada tipo que
quieras buscar (ordenando por price desc con un limit 1)…

Salutaciones,

Isaac Feliu

On Thu, Sep 18, 2008 at 05:02:31PM +0200, Pepe B. wrote:

Product.find(:all, :group => :name, :select => "id, name, MIN(price) as

price")

la consulta me la devuelve bien, el nombre el que toca, el precio mínimo
también, pero como antes, el ID no corresponde con ese producto.

Si pruebas con el GROUP en MySQL no se consigue eso, ya que el ID que se
devuelve es efectivamente, el primero que encuente.

La solución para hacerlo con SQL no es nada sencilla, tendrías que
recurrir a cosas como las descritas en los artículos siguiente:

http://jan.kneschke.de/projects/mysql/groupwise-max

http://www.xaprb.com/blog/2007/03/14/how-to-find-the-max-row-per-group-in-sql-without-subqueries/

Al final, y dependiendo de qué cantidad de datos y cuándo tengas que
hacer esa consulta quizás te sea más rentable recorrer el Array de
objetos del modelo y hacer la operación a manita.

Un saludo.

Por favor,
¿alguien me puede decir poque la consulta devuelte el primer ID?

Siente la insistencia, pero me es un poco urgente.

Gracias a todos.

2008/9/18 Pepe B. [email protected]

Por favor,
¿alguien me puede decir poque la consulta devuelte el primer ID?

Hola Pepe,

como te comentan, el origen del problema es que estás empeñado en hacer
consultas sin entender o aprender SQL. Esto es, gracias a las
abstracciones
de Rails, posible hasta cierto punto, pero llega un momento en que si
seguimos sin ganas de aprender y confiando en la magia, nos estrellamos
en
un muro, que es lo que te está pasando.

Creo que te toca un poco de autoformación. Mucha suerte.

Perdonar por seguir el OT.

Hacerlo en mysql creo que no es tan dificil. Siempre y cuando no se me
olvide algo. o pase algo por alto.
Yo lo haría así:

mysql> create database test33;
Query OK, 1 row affected (0.00 sec)

mysql> use test33;
Database changed
mysql> create table products(id INT, name VARCHAR(256),price INT,
PRIMARY
KEY(id,name));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into products VALUES (1, “camion”, 100), (2, “coche”, 50),
(3,“moto”,25), (4,“camion”,20),(5,“coche”,40);Query OK, 5 rows affected
(0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0

mysql> select name,min(price) as price from products group by name;
±-------±------+
| name | price |
±-------±------+
| camion | 20 |
| coche | 40 |
| moto | 25 |
±-------±------+
3 rows in set (0.00 sec)

mysql> select * from (select name,min(price) as price from products
group by
name) as prices JOIN products USING(name,price);
±-------±------±—+
| name | price | id |
±-------±------±—+
| moto | 25 | 3 |
| camion | 20 | 4 |
| coche | 40 | 5 |
±-------±------±—+
3 rows in set (0.00 sec)

Ahora bien, como se hace eso en rails… Ni idea, probablemente usando
un
map en el resultado del minimun(:group => …)