2011-12-29 4 views
1

J'ai du mal à trouver une déclaration SQL pour cette situation: Imaginez qu'il y ait plusieurs véhicules sur la route à un moment donné, chacun de ces voyages est dans la table des voyages. Chaque véhicule envoie régulièrement les mises à jour de son emplacement actuel (latitude, longitude)Comment choisir parmi 2 tables et obtenir la valeur la plus élevée d'une table?

Il y a 2 tables: current_position

id | trip_id | update_time | lat | lon

voyages

id | état

current_position a plusieurs mises à jour pour chaque voyage

J'ai besoin pour obtenir des résultats, ayant trip_id, lat, lon

pour chaque voyage qui a le statut = « CONDUIRE » et doit avoir les dernières valeurs à partir de current_position

Dernière valeur Je veux dire valeur la plus élevée de update_time. Quand j'ai essayé le GROUP BY, j'ai obtenu des résultats distincts mais les résultats n'étaient pas toujours les derniers. Je ne peux pas sembler combiner l'ordre par update_time DESC avec GROUP BY trip_id

Répondre

1

il semble que vous vouliez sélectionner la ligne current_position avec la plus grande valeur update_time pour un trip_id donné. Vous pouvez le faire avec une sous-requête en utilisant MAX. Editer ... après avoir posté, je me rends compte que vous avez besoin d'une jointure pour obtenir toutes les lignes où le statut de déclenchement correspondant = 'conduire'. Je pense que cela va le faire (bien que je sois plus serveur Sql donc il pourrait y avoir une légère différence avec MySQL je ne suis pas au courant).

Select * from current_position cp 
join trips t on cp.trip_id = t.id 
where t.status = 'Driving' 
and cp.update_time = (select Max(update_time) from current_position where trip_id = t.id) 
+0

Donc, s'il y a 300 voyages en cours alors il y aura 300 sous-requêtes dans cette requête? –

+0

la performance devrait être sans problème pour 300 enregistrements retournés. Essayez-le et voyez. – nycdan

+0

DRapp fait un bon point. Vous pouvez probablement utiliser Max (id) au lieu de Max (update_time) et obtenir de meilleures performances sur les grandes tables. – nycdan

-1

Avec MySQL, groupe par une colonne sans agrégat vous donner la première ligne pour chaque valeur distincte, donc Usegroup par après l'ordre par.

Il est aussi simple que cela:

select trip_id, lat, lon 
from (select * from current_position 
     join trips on trips.id = current_position.id 
     where status = 'DRIVING' 
     order by trip_id, update_time desc) x 
group by trip_id 
+0

current_position n'a pas la colonne 'statut', le statut est dans la table de voyages –

+0

current_position n'a pas de colonne de statut ... –

+0

Merci les gars - J'ai corrigé la requête :) – Bohemian

1

Commencez avec un prequery par ID de voyage et le temps maximum, puis re-joindre à ce retour sur la base la plus récente du temps. Cependant, si la colonne ID de la table des positions actuelles est une colonne auto-incrémentée, et que update_time sera toujours plus grand que le dernier, je changerais plutôt le max() de l'heure au maximum de l'ID de la position actuelle table comme ce serait mieux sur le groupe par et index lors de rejoindre après le "PreQuery"

Je voudrais aussi avoir un index sur votre table de voyages par le statut pour raccourcir vos résultats de requête. Au fur et à mesure de la construction de votre table, si vous commencez à effectuer 10 000 voyages et que seulement 15 sont en cours de livraison (ou quelque chose d'autre), vous n'obtiendrez que les 15 actifs et ne couvrirez pas toute la table des déplacements.

select 
     cp2.* 
    from 
     (select t.id, 
       max(cp.update_time) as MostRecent 
      from 
       trips t 
       join current_position cp 
        on t.id = cp.trip_id 
      where 
       t.status = 'Driving' 
      group by 
       t.id) PreQuery 
     join current_position cp2 
     on PreQuery.id = cp2.trip_id 
     and PreQuery.MostRecent = cp2.update_time 
0

Une autre façon:

SELECT 
    cp.* 
FROM 
     (SELECT id 
      FROM trips 
      WHERE status = 'DRIVING' 
     ) AS t 
    JOIN 
     current_position AS cp 
     ON 
     cp.id = 
     (SELECT cpm.id 
      FROM current_position AS cpm 
      WHERE cpm.trip_id = t.id 
      ORDER BY cpm.update_time DESC 
      LIMIT 1 
     ) 
Questions connexes