sql >> Base de Datos >  >> RDS >> PostgreSQL

Rails 4:el uso de la función PostgreSQL en orden provoca un error en la consulta debido a que la tabla de inclusión no se une

Suponga que necesita obtener el nombre de usuario de las primeras cinco publicaciones. Escribe rápidamente la consulta a continuación y disfruta de tu fin de semana.

posts = Post.limit(5)

posts.each do |post|
  puts post.user.name
end

Bien. Pero veamos las consultas

Post Load (0.5ms)  SELECT  `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 2 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 2 LIMIT 1
User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE  `users`.`id` = 1 LIMIT 1

1 query para obtener todas las posts y 1 query para obtener users por cada publicación da como resultado un total de 6 queries . Consulte la solución a continuación que hace lo mismo, solo en 2 queries :

posts = Post.includes(:user).limit(5)

posts.each do |post|
  puts post.user.name
end

#####

Post Load (0.3ms)  SELECT  `posts`.* FROM `posts` LIMIT 5
User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` IN (1, 2)

Hay una pequeña diferencia. Agregar includes(:posts) a su consulta, y problema resuelto. Rápido, agradable y fácil.

Pero no se limite a agregar includes en su consulta sin entenderlo correctamente. Usar includes con joins podría resultar en uniones cruzadas dependiendo de la situación, y no es necesario en la mayoría de los casos.

Si desea agregar condiciones a sus modelos incluidos, deberá hacer referencia explícita a ellos . Por ejemplo:

User.includes(:posts).where('posts.name = ?', 'example')

Lanzará un error, pero esto funcionará:

User.includes(:posts).where('posts.name = ?', 'example').references(:posts)

Tenga en cuenta que includes funciona con association names mientras references necesita the actual table name .