IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Comment avoir la liste des patients absents à leurs 3 derniers Rdv


Sujet :

Langage SQL

  1. #1
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut Comment avoir la liste des patients absents à leurs 3 derniers Rdv
    Bonjour,
    J'ai 1 table Patient (Id, Nom...) et 1 Table RdvPatient (IdPatient, Date, IsAbsent...).
    Comment demander la liste des patient absents à leurs X derniers Rdv (par date), X devant être 1 paramètre passé.
    Merci pour votre aide
    PS : Sql Server 2014

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    WITH 
    T0 AS
    -- recherche des trois derniers RV du patient
    (SELECT PRV_ID, PAT_ID,  
            ROW_NUMBER() OVER(PARTITION BY PAT_ID ORDER BY RDV_DATE_HEURE DESC) AS N
     FROM   T_PATIENT_RENDEZVOUS_PRV),
    T1 AS
    -- y a t-il un des 3 derniers RV qui a été honoré ?
    (SELECT PAT_ID
     FROM   T_PATIENT_RENDEZVOUS_PRV AS PRV
            JOIN T0 ON PRV.PRV_ID = T0.PRV
     WHERE  PRV_PRESENT = 10)
    -- résultat final
    SELECT *
    FROM   T_PATIENT_PAT AS PAT
    WHERE  PAT_ID IN (SELECT PAT_ID
                      FROM   T0
                      EXCEPT
                      SELECT PAT_ID
                      FROM   T1);
    Pour vous former, mon livre sur SQL :
    Nom : SQL.jpg
Affichages : 257
Taille : 47,4 Ko

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 137
    Points : 1 917
    Points
    1 917
    Par défaut
    Bonjour,

    Voici une solution utilisant des fonctions analytiques. J'ai supposé que IsAbsent = 1 pour signaler une absence. La requête ne montre que les patients ayant manqué leurs X derniers rdv, avec les dates correspondantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    with rdv as (select p.id,
                        p.nom, 
                        r.date_rdv,
                        row_number() over (partition by p.id order by r.date_rdv desc) rn,
                        sum(case when r.isabsent = 1 then 1 else 0 end) over (partition by p.id order by r.date_rdv desc) somme_rdv_absent
                 from patient p
                 join RdvPatient r on r.idpatient = p.id
                ),
         X_derniers_rdv as (select id, 
                                   nom,
                                   date_rdv,
                                   max(somme_rdv_absent) over (partition by id) nb_rdv_manques
                            from rdv
                            where rn <= :X
                           )
    select id, 
           nom,
           date_rdv
    from X_derniers_rdv
    where nb_rdv_manques = :X;

  4. #4
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 137
    Points : 1 917
    Points
    1 917
    Par défaut
    Si tu es en Oracle 12c, c'est encore plus simple avec une requête match_recognize:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    select id, nom, date_rdv 
    patient p
    join RdvPatient r on r.idpatient = p.id
    match_recognize
     (partition by id
      order by date_rdv desc
      all rows per match
      pattern(^rdv_manque{:X})
      define rdv_manque as rdv_manque.isabsent=1
     );

  5. #5
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    bonjour,

    Ou bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    WITH RangRDV AS (
    		SELECT *, ROW_NUMBER() OVER(PARTITION BY idpatient ORDER BY dte DESC) AS RN
    		FROM RdvPatient
    	)
    SELECT p.Nom
    FROM Patient AS P
    INNER JOIN RangRDV AS R
    	ON	R.idpatient = P.id
    WHERE RN <= @x
    GROUP BY p.Nom
    HAVING SUM(IsAbsent)  = 3

  6. #6
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Bonjour,

    Voici une solution utilisant des fonctions analytiques. J'ai supposé que IsAbsent = 1 pour signaler une absence. La requête ne montre que les patients ayant manqué leurs X derniers rdv, avec les dates correspondantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    with rdv as (select p.id,
                        p.nom, 
                        r.date_rdv,
                        row_number() over (partition by p.id order by r.date_rdv desc) rn,
                        sum(case when r.isabsent = 1 then 1 else 0 end) over (partition by p.id order by r.date_rdv desc) somme_rdv_absent
                 from patient p
                 join RdvPatient r on r.idpatient = p.id
                ),
         X_derniers_rdv as (select id, 
                                   nom,
                                   date_rdv,
                                   max(somme_rdv_absent) over (partition by id) nb_rdv_manques
                            from rdv
                            where rn <= :X
                           )
    select id, 
           nom,
           date_rdv
    from X_derniers_rdv
    where nb_rdv_manques = :X;
    Merci pour ton aide.
    Le résultat n'est pas tout à fait celui attendu : si je demande la liste des ceux absents aux 3 derniers Rdv, le patient sort 3 fois avec chaque fois la date du Rdv.
    ...je voulais 1 liste de patients (chacun 1 seule fois), pas 1 liste de Rdv manqués.
    Je pense qu'on doit pouvoir la modifier pour cela mais c'est trop complexe pour mon petit niveau...

  7. #7
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    WITH 
    T0 AS
    -- recherche des trois derniers RV du patient
    (SELECT PRV_ID, PAT_ID,  
            ROW_NUMBER() OVER(PARTITION BY PAT_ID ORDER BY RDV_DATE_HEURE DESC) AS N
     FROM   T_PATIENT_RENDEZVOUS_PRV),
    T1 AS
    -- y a t-il un des 3 derniers RV qui a été honoré ?
    (SELECT PAT_ID
     FROM   T_PATIENT_RENDEZVOUS_PRV AS PRV
            JOIN T0 ON PRV.PRV_ID = T0.PRV
     WHERE  PRV_PRESENT = 10)
    -- résultat final
    SELECT *
    FROM   T_PATIENT_PAT AS PAT
    WHERE  PAT_ID IN (SELECT PAT_ID
                      FROM   T0
                      EXCEPT
                      SELECT PAT_ID
                      FROM   T1);
    Merci, ça a l'air de faire pas mal mais je ne comprends pas ou je peux donner le nombre d'absences souhaitées...

  8. #8
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Si tu es en Oracle 12c, c'est encore plus simple avec une requête match_recognize:
    ...hélas non, j'avais oublié de préciser : Sql Server 2014

  9. #9
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    bonjour,

    Ou bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    WITH RangRDV AS (
    		SELECT *, ROW_NUMBER() OVER(PARTITION BY idpatient ORDER BY dte DESC) AS RN
    		FROM RdvPatient
    	)
    SELECT p.Nom
    FROM Patient AS P
    INNER JOIN RangRDV AS R
    	ON	R.idpatient = P.id
    WHERE RN <= @x
    GROUP BY p.Nom
    HAVING SUM(IsAbsent)  = 3
    Merci, ça me plait bien comme technique mais j'avais simplifié en pensant que je pourrais adapter... et je n'y arrive pas.
    En fait je n'ai pas IsAbs = 1 mais AbsID qui vaut 1 à 49 qd c'est 1 absence...
    Si tu pouvais me proposer ta solution en adaptant cette variante ce serait parfait.

  10. #10
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    et quand ce n'est pas une absence ?

  11. #11
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 137
    Points : 1 917
    Points
    1 917
    Par défaut
    Citation Envoyé par bib34690 Voir le message
    Merci pour ton aide.
    Le résultat n'est pas tout à fait celui attendu : si je demande la liste des ceux absents aux 3 derniers Rdv, le patient sort 3 fois avec chaque fois la date du Rdv.
    ...je voulais 1 liste de patients (chacun 1 seule fois), pas 1 liste de Rdv manqués
    Oui c'était pour avoir les dates de rdv manqués. Si tu n'en as pas besoin alors utilises la version de aieeeuuuuu.

  12. #12
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 137
    Points : 1 917
    Points
    1 917
    Par défaut
    tu peux modifier la clause having:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HAVING SUM(case when IsAbsent between 1 and 49 then 1 else 0 end)  = 3

  13. #13
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Sur SQL-Server vous pouvez faire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    declare @N int;
    set @N=3;
     
         select P.Id, P.Nom
           from Patient as P
    cross apply (  select top (@N)
                           case when R.AbsID between 1 and 49 then 1 else 0 end
                     from RdvPatient as R
                    where R.IdPatient = P.Id
                 order by R.[Date] desc
                ) as A (IsAbsent)
       group by P.Id, P.Nom
         having sum(A.IsAbsent) = @N;
    Le 3 étant dans le top du cross apply et dans le having final.

    Edit: prise en compte de l'AbsID et paramétrisation du nombre d'absences.

  14. #14
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    et quand ce n'est pas une absence ?
    0= Present
    51 à 100 c'est le médecin qui est absent.
    On fait un suivi des absences du patient : les abs. du médecin sont considérées comme des présences pour cette requête

  15. #15
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    tu peux modifier la clause having:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HAVING SUM(case when IsAbsent between 1 and 49 then 1 else 0 end)  = 3
    PARFAIT : fait le job, simple à comprendre, rapide.
    Merci

  16. #16
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Je n'ai pas réussi à comprendre et à faire fonctionner la solution de SQLpro. Dommage, j'aurais bien aimé comparer.
    La solution de vanareg ne répond pas à mon besoin.
    La solution de Waldar etait la plus concise et me plaisait bien mais elle etait trés lente.
    J'ai retenu la solution de aieeeuuuuu : 3 fois plus rapide sur ma base, simple et concise.

    Merci à SQLpro, vanagreg, Waldar et aieeeuuuuu.
    Mon problème a été réglé rapidement et efficacement grâce à vous.
    Bon WE

  17. #17
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    bonjour,

    LA solution de Waldar pourrait être efficace, mais à condition qu'il y ait un index adéquat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CREATE INDEX IX_RdvPatient_IdPatient ON RdvPatient (IdPAtient) INCLUDE (IsAbsent)

  18. #18
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Il manquait dans ma solution un petit bout de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    WITH 
    T0 AS
    -- recherche des trois derniers RV du patient
    (SELECT PRV_ID, PAT_ID,  
            ROW_NUMBER() OVER(PARTITION BY PAT_ID ORDER BY RDV_DATE_HEURE DESC) AS N
     FROM   T_PATIENT_RENDEZVOUS_PRV),
    T1 AS
    -- y a t-il un des 3 derniers RV qui a été honoré ?
    (SELECT PAT_ID
     FROM   T_PATIENT_RENDEZVOUS_PRV AS PRV
            JOIN T0 ON PRV.PRV_ID = T0.PRV
     WHERE  PRV_PRESENT = 1
       AND  N <= 3) --> nombre de RV consécutifs
    -- résultat final
    SELECT *
    FROM   T_PATIENT_PAT AS PAT
    WHERE  PAT_ID IN (SELECT PAT_ID
                      FROM   T0
                      EXCEPT
                      SELECT PAT_ID
                      FROM   T1);
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  19. #19
    Membre habitué
    Profil pro
    Développeur informatique
    Inscrit en
    Juin 2002
    Messages
    264
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juin 2002
    Messages : 264
    Points : 175
    Points
    175
    Par défaut
    Merci pour ces précisions.
    J'ai pu faire les tests avec toutes ces solutions, celle de aieeeuuuuu reste la plus rapide et la plus simple.
    ...fin des tests, dossier clos !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Python 2.X] comment avoir la list des EVT_ et leur actions ?
    Par tsumey dans le forum wxPython
    Réponses: 5
    Dernier message: 28/03/2016, 08h42
  2. Réponses: 1
    Dernier message: 04/04/2013, 00h26
  3. Réponses: 4
    Dernier message: 26/03/2009, 14h58
  4. comment avoir la liste des programmes dans le systray ? Merci
    Par eric_xrx dans le forum VB 6 et antérieur
    Réponses: 0
    Dernier message: 25/01/2009, 20h00
  5. Réponses: 3
    Dernier message: 17/08/2007, 16h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo