2010-07-19 8 views
4

Dans un post précédent, je faisais une base de données très simple avec 3 tables "médecin", "patient" et "visite". J'ai essayé de le rendre plus réaliste et inclus maintenant une relation de plusieurs à plusieurs entre "médecin" et "patient". "visite" est le tableau résultant de cette relation n-m. Je suppose que la structure simple suivante pour ma table:Aide sur une requête SQL

 
doctor 
- idDoctor 
- name 

patient 
-idPatient 
-name 
-dob 

visit 
-idVisit 
-idPatient 
-idDoctor 
-timestamp 

J'utilise les données suivantes sur lequel je veux faire une requête:

 
idVisit idDoctor idPatient timestamp 
1  1   1   2010-07-19 14:10 
2  1   2   2010-07-19 15:10 
3  2   1   2010-07-19 15:10 
4  3   1   2010-07-19 16:10 
5  2   2   2010-07-19 18:10 
6  2   3   2010-07-19 19:10 
7  1   1   2010-07-19 20:10 

Je puis 3 patients et 3 médecins. Par exemple, le patient 1 est allé deux fois voir le médecin 1, le médecin 2 fois et le médecin 3 fois.

Je voudrais construire ma demande de sorte que pour chaque couple (médecin, patient) j'ai la dernière visite . Cette requête devrait renvoyer les visites d'identification (2,3,4,5,6, 7) et non 1 parce que la dernière visite que le patient a payé au docteur 1 était à 20:10 et pas à 14:10. Comment pourrais-je faire ça?

J'apprécie vraiment vos commentaires et votre aide. Cela m'aide vraiment à améliorer mes conceptions lorsque je commence à utiliser SQL.

+0

Quelle base de données utilisez-vous? SQL Server, Oracle, MySQL ou autre chose? –

+0

Je ne nommerais pas un horodatage de colonne car il peut s'agir d'un mot réservé dans certaines bases de données. – HLGEM

Répondre

4

ids sont attribués en supposant l'ordre chronologique, vous pouvez "tricher"

SELECT MAX(idVisit) AS idVisit, idDoctor, idPatient 
FROM visit 
group by idDoctor, idPatient 

Si cette hypothèse ne peut être

SELECT v.idVisit, v.idDoctor, v.idPatient 
FROM visit v 
WHERE NOT EXISTS 
(
    SELECT * FROM visit v2 
    WHERE v2.idDoctor = v.idDoctor 
    AND v.idPatient = v2.idPatient 
    AND v2.timestamp > V.timestamp 
) 

Ou, si votre SGBD prend en charge,

WITH V AS 
(
SELECT idVisit, idDoctor, idPatient, 
row_number() over(partition by idDoctor, idPatient order by timestamp desc) AS RN 
FROM visit 
) 

SELECT idVisit, idDoctor, idPatient 
FROM V 
WHERE RN=1 
+0

L'hypothèse rendrait les choses beaucoup plus faciles, mais souvent dans ces systèmes, les visites peuvent être planifiées hors de l'ordre dans lequel elles se produisent, donc ce n'est probablement pas réaliste. – FrustratedWithFormsDesigner

+0

@Frustrated - Oui je suis d'accord. C'est peu probable dans le monde réel. –

+0

La deuxième solution fonctionne parfaitement! Merci beaucoup ! – am38

1
select v.idVisit, d.idDoctor, d.name as nameDoctor, p.idPatient, p.name as namePatient, v.timestamp as lastVisit 
from visit v 
join doctor d on v.idDoctor = d.idDoctor 
join patient p on v.idPatient = p.idPatient 
where not exists 
    (select 1 from visit where idDoctor = v.idDoctor and idPatient = v.idPatient and timestamp > v.timestamp) 
0

Oracle a nalytics answer:

SELECT idVisit, idDoctor, idPatient, 
     max(timestampVisit) 
     over (partition by idDoctor, idPatient) as timestampVisit 
    FROM visits 
+0

Je peux bien me tromper mais cela ne retournera-t-il pas simplement le 'max (timestampVisit)' plutôt que le 'idVisit' qui est lié au' max (timestampVisit) '? –