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 :

Récupérer un champs à null si une entrée n'existe pas


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Inscrit en
    Avril 2006
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 7
    Par défaut Récupérer un champs à null si une entrée n'existe pas
    Bonjour,

    Je cherche à optimiser une page ASP comportant de multiples accès à une base de données (Access) et je pense pouvoir réduire le nombre de requêtes.

    Ma base dispose d'une table Projet et d'une table Etat. Un projet peut avoir plusieurs états ou aucun état.

    J'aimerai, avec un seul select, trouver pour chaque projet son nom et son état le plus récent.

    Pour l'instant je fais 2 requêtes (je simplifie) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select id, nom From Projet
    puis pour chaque projet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select e.typeEtat From Etat e Where idProjet = ? And e.date = (SELECT MAX(e2.date) From Etat e2 Where e2.idProjet = ?)
    où les deux paramètres sont l'id du projet et si aucune ligne n'est retournée à la deuxième requête, le projet n'a donc pas d'état.

    J'aimerai en un seul select obtenir le nom et le type d'état le plus récent pour ce projet en le mettant à null si le projet n'a pas d'état.

    Je pensais utiliser un Left Join mais je ne connais pas trop les possibilités du Join. Pour le moment, avec le join je récupère tous les états des projets grâce à cette requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT p.nom, e.typeEtat FROM Projet p LEFT JOIN Etat e ON p.id=e.idProjet
    Mais je ne parviens pas à récupérer uniquement l'état le plus récent.

    Comment faire ? Est-ce possible ?

    Merci d'avance pour votre aide.

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 683
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 683
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT p.nom, e.typeEtat 
    FROM Projet p 
    	LEFT JOIN Etat e 
    		ON p.id=e.idProjet
    		AND e.date = (	SELECT MAX(e2.date) 
    				FROM Etat e2 
    				WHERE e2.idProjet = e.idProjet
    				)
    Si vous avez deux états à une même date max, vous aurez deux lignes "projet".

    Malheureusement, Access ne supporte pas les clauses de jointure avec sous requête corrélée. Donc cette requête ne s'executera pas.

  3. #3
    Membre du Club
    Inscrit en
    Avril 2006
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 7
    Par défaut
    Effectivement ça ne fonctionne pas. J'obtient une erreur 80040E14 (erreur de syntaxe).

    Il n'y a donc aucun moyen de faire cela en une requête avec Access ?

  4. #4
    Expert éminent
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 212
    Billets dans le blog
    16
    Par défaut
    Quelque chose comme ça ?

    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
    Select Nom, typeEtat
    from   Projet as p, Etat as e, 
          (Select idprojet, max(DateEtat) as DateEtat
           from   Etat
           group by idProjet) as x
    where p.idprojet = x.idprojet
    and   x.idprojet = e.idprojet
    and   e.DateEtat = x.DateEtat
    Union all
    Select Nom, '--'
    from   Projet as p
    where not exists
         (select *
          from   etat e
          where p.idprojet = e.idprojet)
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  5. #5
    Expert éminent
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 212
    Billets dans le blog
    16
    Par défaut
    Variante : Left Join et Inner Join

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Select p.nom, y.typeEtat
    From   Projet p left join
          (Select e.idprojet, e.typeEtat, e.dateEtat
           From   Etat e  Inner Join  
                 (Select idprojet, max(DateEtat) as DateEtat
                  from   Etat
                  group by idProjet) as x
                On e.idprojet = x.idprojet and e.DateEtat = x.DateEtat) as y
            on p.idprojet = y.idprojet
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  6. #6
    Expert éminent
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 212
    Billets dans le blog
    16
    Par défaut
    Autre variante :

    Vous pouvez encore procéder par vues de jointures.

    Exemple :

    1) Création d'une 1re requête faisant office de vue et que l'on appelle par exemple Select_MAX :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT   idprojet, max(DateEtat) AS DateEtat
    FROM     Etat 
    GROUP BY idProjet
    2) Création d'une 2e requête faisant office de vue elle aussi et que l'on appelle par exemple Select_TypeEtat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT    e.idprojet, e.typeEtat
    FROM      Etat AS e INNER JOIN Select_Max AS x 
                 ON e.idProjet = x.idProjet AND e.DateEtat = x.DateEtat
    3) Le résultat est obtenu par exécution de la requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT    p.idprojet, y.typeEtat
    FROM      Projet AS p LEFT JOIN Select_TypeEtat AS y 
                  ON p.idprojet = y.idprojet
    (a) Faites simple, mais pas plus simple ! (A. Einstein)
    (b) Certes, E=mc², mais si on discute un peu, on peut l’avoir pour beaucoup moins cher... (G. Lacroix, « Les Euphorismes de Grégoire »)
    => La relativité n'existerait donc que relativement aux relativistes (Jean Eisenstaedt, « Einstein et la relativité générale »)

    __________________________________
    Bases de données relationnelles et normalisation : de la première à la sixième forme normale
    Modéliser les données avec MySQL Workbench
    Je ne réponds pas aux questions techniques par MP. Les forums sont là pour ça.

  7. #7
    Membre du Club
    Inscrit en
    Avril 2006
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 7
    Par défaut
    Merci pour ces solutions.

    J'ai pas testé mais la seconde me parait plus simple à utiliser.

    J'ai d'autres jointures à faire sur le même principe dans la même requête et la première solution avec le UNION double le nombre de Select à faire à chaque fois.

    Je testerai ça demain.

    Après je sais pas si une requête plus complexe est plus efficace que plusieurs requêtes simples.

    EDIT : Je répondais au post précédent, vais lire cette dernière solution.
    EDIT2 : L'idée des views ça peut être pas mal aussi. Merci

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

Discussions similaires

  1. Null sur une colonne qui existe pas
    Par punisher999 dans le forum NHibernate
    Réponses: 0
    Dernier message: 27/06/2012, 17h49
  2. Nbre de champs à NULL dans une table ?
    Par Pilgrimm01 dans le forum SQL
    Réponses: 4
    Dernier message: 17/07/2007, 15h46
  3. Réponses: 2
    Dernier message: 29/12/2006, 15h56
  4. Réponses: 12
    Dernier message: 19/12/2006, 12h26
  5. Réponses: 5
    Dernier message: 28/04/2006, 11h55

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