2012-09-20 6 views
1

J'ai une section en vedette dans mon site Web qui contient des messages en vedette de trois types: normal, grand et petit. Actuellement, je suis aller chercher les trois types en trois requêtes distinctes comme ceci:Rails Optimisation de requête SQL

@featured_big_first = Post.visible.where(pinged: 1).where('overlay_type =?', :big).limit(1) 
@featured_big_first = Post.visible.where(pinged: 1).where('overlay_type =?', :small).limit(1) 
@featured_big_first = Post.visible.where(pinged: 1).where('overlay_type =?', :normal).limit(5) 

Fondamentalement, je suis à la recherche d'une requête qui combinera les trois à un et aller chercher 1 grand, 1 petit, 5 messages normaux.

Répondre

1

Je ne pense pas que ce soit possible, mais vous pouvez utiliser scope qui est plus rails façon d'écrire un code

En outre, il peut juste une faute de frappe mais vous réaffectant le @featured_big_first il contiendra les données du dernier requête seulement

dans post.rb

scope :overlay_type_record lamda{|type| joins(:visible).where(["visible.pinged=1 AND visible.overlay_type =", type])} 

et dans le contrôleur

@featured_big_first = Post.overlay_type_record(:big).limit(1) 
@featured_small_first = Post.overlay_type_record(:small).limit(1) 
@featured_normal_first = Post.overlay_type_record(:normal).limit(5) 
+1

Merci pour la suggestion, je vais l'implémenter. Je vais attendre un peu avant d'accepter votre réponse, b/c je crois que c'est possible avec une requête sql personnalisée avec 'UNION'. – zevstatiev

+0

Oui bien sûr, même si je voudrais apprendre une nouvelle chose :) – Salil

2

Je serais surpris si vous ne voulez pas une commande. Comme vous l'avez, il est censé trouver un grand aléatoire, petit grand, et aléatoire 5 aléatoire.

Oui, vous pouvez utiliser UNION. Cependant, vous devrez exécuter un SQL. Regardez le journal pour le SQL pour chacune de vos trois requêtes, et exécutez un SQL d'une chaîne qui est chacune des trois requêtes avec UNION entre. Cela pourrait fonctionner, ou il pourrait avoir des problèmes avec la limite.

Il est possible en SQL en joignant la table à lui-même, en faisant un groupe par sur un des alias pour la table, un où où l'autre table est < = le groupe par table, et en ajoutant une clause having nombre de < = le tableau est sous la limite.

Donc, si vous aviez une simple requête de la table des postes (sans les conditions visibles et ping,) et je voulais les dossiers avec la dernière date de created_at, la requête normale serait:

SELECT posts1.* 
FROM posts posts1, posts posts2 
WHERE posts2.created_at >= posts1.create_at 
    AND posts1.overlay_type = 'normal' 
    AND posts2.overlay_type = 'normal' 
GROUP BY posts1.id 
HAVING count(posts2.id) <= 5 

Prenez cette SQL, et ajoutez vos conditions pour visible et ping, en n'oubliant pas d'utiliser la condition pour les deux posts1 et posts2. Ensuite, écrivez les grandes et petites versions et combinez tous les éléments.

Je collerais avec les trois appels de base de données.