2013-09-06 6 views
0

J'ai une application qui utilise php et mysql qui permet aux utilisateurs d'ajouter plusieurs prix dans plusieurs devises selon l'emplacement.Requête mysql avancée avec plusieurs jointures, sous-requêtes et rayon

La base de données actuelle ressemble à quelque chose comme ça ... »

Les unités peuvent avoir plusieurs positions qui peuvent avoir plusieurs prix ...

units 
    -id 

positions 
    -id 
    -unit_id 
    -lat 
    -lng 

prices 
    -id 
    -position_id 
    -currency_id 
    -price 
    -min_price 
    -weight 
    -cu_meters 

currencies 
    -id 
    -iso 
    -name 

rates 
    -id 
    -from_currency_id 
    -to_currency_id 
    -rate 

Ce que je besoin est d'obtenir le prix le moins cher (converti en euros donc je peux les comparer) groupés par position triés par les positions les plus proches regroupées par unité.

Ce que je fais maintenant est d'abord obtenir tous les identifiants de position de la table de prix.

SELECT id, position_id 
FROM (SELECT * FROM prices ORDER BY price, min_price) AS p 
WHERE weight >= ".self::connection()->escape($weight)." 
AND cu_meters >= ".self::connection()->escape($cu_meters)." 
GROUP BY position_id 
ORDER BY price, min_price 

Ensuite, obtenir les plus proches des positions avec le résultat de la requête précédente

SELECT id, unit_id, lat, lng 
FROM 
    (
     SELECT 
      id, 
      unit_id, 
      lat, 
      lng, 
      return_position, 
      return_lat, 
      return_lng, 
      (6371 * acos(cos(radians(".Position::connection()->escape($lat).")) * cos(radians(lat)) * cos(radians(lng) - radians(".Position::connection()->escape($lng).")) + sin(radians(".Position::connection()->escape($lat).")) * sin(radians(lat)))) AS distance 
     FROM positions 
     ORDER BY distance ASC 
    ) AS pos 
WHERE id IN(".implode(",", array_keys($position_ids)).") 
GROUP BY unit_id 
ORDER BY distance ASC 
LIMIT 20; 

Je dois ajouter une requête pour obtenir le taux de conversion des devises et convertir le prix en euros, donc je comprends vraiment la prix le moins cher dans la première requête si elles sont en euros, livres ou dollars.

Est-il possible de faire tout cela en une seule requête. Quel est le moyen le plus efficace de le faire

Merci! /Mattias

Répondre

0

Vous pouvez simplement exécuter cette première requête en tant que sous-sélection, par ex.

WHERE id IN (
    SELECT id FROM prices ORDER BY price, min_price) AS p 
    WHERE weight >= ".self::connection()->escape($weight)." 
    AND cu_meters >= ".self::connection()->escape($cu_meters)." 
    GROUP BY position_id 
    ORDER BY price, min_price 
) 

La seule fois où vous voudriez les exécuter sous forme de requêtes séparées est si vous voulez garder ces ID de la sous-requête à d'autres fins. Mais si vous n'en avez pas besoin ailleurs dans le script, alors la sous-sélection sera plus efficace, mais en supprimant au moins une séquence d'analyse SQL.

Questions connexes