Trier par requête SQL à l'aide d'un paramètre d'URL
-
11-12-2019 - |
Question
J'ai cette énorme requête laide ci-dessous, j'aimerais la trier dans une vue catalogue.Penser à quelque chose comme http://wow.dev:3000/catalog_items?&order=deals.Un million de mercis d'avance pour tout commentaire ou réponse.
select 100 - round((current_price / item.estimated_price)*100) as percent, item.cached_thumbnail_url, item.item_id, it.name,
ci.current_price, ci.close_date
from item
join catalog_item ci on ci.item_id = item.item_id
join item_translations as it on (it.item_id = item.item_id)
where (100 - round((current_price / item.estimated_price)*100)) > 49 and
item.estimated_price > 0 and ci.current_price > 0 and ci.close_date > now() and item.active = 1 and ci.active = 1 and
(current_price / estimated_price) < 1
order by (ci.close_date < DATE_ADD(now(), INTERVAL 17 hour)) and (item.estimated_price - current_price) desc
limit 12
La solution
Je ne sais pas comment cela pourrait être lié au ROR, mais quand même :
Tu as
100 - round((current_price / item.estimated_price)*100) as percent
dans votre clause SELECT, mais de toute façon en utilisant la même expression dans les conditions WHERE.Peut
item.estimated_price
être inférieur à zéro ?Sinon leitem.estimated_price > 0
la condition est excessive, si elle est nulle, le(100 - round((current_price / item.estimated_price)*100)) > 49
la condition sera fausseLe
(current_price / estimated_price) < 1
est excessif pour les mêmes raisons
Votre requête peut donc être réécrite un peu plus clairement comme ceci :
select (100 - round((current_price / item.estimated_price)*100)) as percent,
item.cached_thumbnail_url, item.item_id, it.name,
ci.current_price, ci.close_date
from item
join catalog_item ci on ci.item_id = item.item_id
join item_translations as it on (it.item_id = item.item_id)
where
percent > 49
and ci.current_price > 0
and ci.close_date > now()
and item.active = 1
and ci.active = 1
order by
(ci.close_date < DATE_ADD(now(), INTERVAL 17 hour))
and (item.estimated_price - current_price) desc
limit 12
Cela n'améliore pas beaucoup la situation, mais je ne peux pas en dire plus sans connaître d'autres raisons concernant votre architecture DB.
BTW, le lien dans votre question ne fonctionne pas (c'est votre lien local évidemment)
Autres conseils
En vous basant sur la réponse du code binaire, vous pouvez essayer d'encapsuler votre requête dans ARel, puis dans l'action de votre contrôleur, vous ordonneriez sur le champ transmis dans le hachage des paramètres, quelque chose comme ceci :
class ItemsController < ApplicationController
...
def index
@items = Item.select(%{(100 - round((current_price / item.estimated_price)*100)) as percent,
item.cached_thumbnail_url, item.item_id, it.name,
ci.current_price, ci.close_date}).
joins('join catalog_item ci on ci.item_id = item.item_id').
joins('join item_translations as it on (it.item_id = item.item_id)').
where('percent > 49 and ci.current_price > 0 and ci.close_date > now() and item.active = 1 and ci.active = 1').
order(%{(ci.close_date < DATE_ADD(now(), INTERVAL 17 hour))
and (item.estimated_price - current_price) desc)}).limit(12)
@items = @items.order(params[:order]) if params[:order]
...
end
MODIFIER
Comme le code binaire le souligne ci-dessous, vous souhaiterez peut-être rendre le code du contrôleur plus propre en déplaçant la requête principale en dehors de l'action, probablement dans une méthode du Item
modèle, et en vous assurant de toujours retourner un Relation
objet à partir de celui-ci (comme le fait l'instruction actuelle), afin que vous puissiez enchaîner l'extra order
plus tard:
def index
@items = Item.by_price_ratio
@items = @items.order(params[:order]) if params[:order]
end