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

Requêtes et SQL. Discussion :

Requête concaténation sur champ multivalué


Sujet :

Requêtes et SQL.

  1. #1
    Membre confirmé
    Femme Profil pro
    Chercheuse Sciences humaines
    Inscrit en
    Juillet 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Chercheuse Sciences humaines

    Informations forums :
    Inscription : Juillet 2014
    Messages : 33
    Par défaut Requête concaténation sur champ multivalué
    Bonjour,
    Mon problème est relativement simple mais je n'arrive pas à trouver de solution : j'aimerais concaténer un champ multivalué avec un (ou plusieurs) champs simples en vue de la publication d'un état ou d'un publipostage sous word.
    Dans ma requête, il y a les champs PERTURB et TYPE_PERTURB multivalué. Il n'existe pas de table pour les valeurs de TYPE_PERTURB mais seulement TYPE_PERTURB.Value.

    J'aimerais créer un champ de requête Perturbation : [PERTURB] & [TYPE_PERTURB] valeur 1, valeur 2, valeur 3... pour chaque enregistrement (et selon les valeurs sélectionnées/cochées). Il y a donc une requête IIF qui se glisse aussi dans tout ça...
    Soit concaténer les champs visibles dans le résultat de la requête dans l'image jointe.

    J'ai essayé de m'inspirer de plusieurs conversations du forum, des FAQ et autres tuto dont celui de Warin mais je ne trouve rien.
    J'arrive à utiliser le code très utile donné par LedZeppII dans cette discussion.
    J'arrive à créer une requête qui met à plat les relations ID_FAIT et TYPE_PERTURB.Value (comme ici) mais ce n'est pas vraiment ce que je cherche à faire.
    J'ai cherché dans le support Office et dans divers sites y compris en anglais mais je n'ai pas trouvé, il me manque certainement des connaissances en codage et je n'ai peut-être pas utilisé les bons mots clés...

    Voilà l'ébauche de code que je souhaiterais utiliser, en remplaçant les valeur1, valeur2, valeur3, etc.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    VraiFaux([TAB_FAIT_FUN]![PERTURB]=0;"Pas de perturbation identifiée";"Fait perturbé :") & VraiFaux(NbCar(Nz([TAB_FAIT_FUN]![TYPE_PERTURB];""))>0; valeur 1, valeur 2, valeur 3 ; "")
    Je peux fournir plus de détails si ce n'est pas assez limpide.
    Merci beaucoup

    Nom : xREQetat_PERTURB2.jpg
Affichages : 1565
Taille : 126,3 Ko

  2. #2
    Modérateur

    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    15 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2005
    Messages : 15 437
    Par défaut
    Bonjour.

    À mon avis les champs multivalués sont une plaie.

    Ici un bon article sur comment s'en servir.
    Using multivalued fields in queries
    https://support.office.com/en-us/art...3-b6624e1e323a


    Pour concaténer tes résultats, je ferai une requête qui va me donner toutes les valeurs par personne. Quelque chose comme :

    ReqValeur :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select [TaTable].[TonID], [TaTable].[TYPE_PERTURB].Value as Valeur
    from [TaTable];

    Après on est ramené au cas classique de concaténation de valeur.

    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
    22
    public function Cancatener(prmTonID as long) as string
       dim result as string
       dim db as dao.database:set db=currentdb
       dim r as dao.recordset:set r=db.openrecordset("reqValeur", dbOpenSnapshot)
       dim critere as string:critere="[TonID]=" & prmTonID
     
       call r.findfirst(critere)
     
       do while not r.nomatch
     
          if result <>"" then
            result=result & "; "
          end if
     
          result=result & r![Valeur]
          call r.findnext(critere)
       loop
     
       r.close:set r=nothing
       db.close:set db=nothing
       Concatener=result
    end function
    A+
    Vous voulez une réponse rapide et efficace à vos questions téchniques ?
    Ne les posez pas en message privé mais dans le forum, vous bénéficiez ainsi de la compétence et de la disponibilité de tous les contributeurs.
    Et aussi regardez dans la FAQ Access et les Tutoriaux Access. C'est plein de bonnes choses.

  3. #3
    Membre confirmé
    Femme Profil pro
    Chercheuse Sciences humaines
    Inscrit en
    Juillet 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Chercheuse Sciences humaines

    Informations forums :
    Inscription : Juillet 2014
    Messages : 33
    Par défaut
    Bonjour marot_r et merci pour ton aide,

    Oui j'ai bien compris que les champs multivalués n'étaient pas si bien qu'ils en ont l'air, du moins sont assez trompeurs... bon, mais quand on a besoin de définir plusieurs variables d'un même champ pour un même individu, comment on fait ? plein de champs booléens oui/non ?
    Quelle serait la méthode pour palier à ce problème ? je n'ai pas l'impression de la trouver alors que j'ai lu cette critique des champs multivalués à beaucoup d'endroits (mais je ne prétends pas avoir tout lu... ou compris tout ce que j'ai lu )

    Bon mais revenons à nos moutons, si l'on garde le format multivalué... ok pour le premier code, j'ai déjà la requête qui va bien (cf. images)

    Par contre pour ce qui est du second,
    cas classique de concaténation de valeur.

    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
    22
    public function Cancatener(prmTonID as long) as string
           dim result as string
           dim db as dao.database:set db=currentdb
           dim r as dao.recordset:set r=db.openrecordset("reqValeur", dbOpenSnapshot)
           dim critere as string:critere="[TonID]=" & prmTonID
     
           call r.findfirst(critere)
     
           do while not r.nomatch
     
              if result <>"" then
                result=result & "; "
              end if
     
              result=result & r![Valeur]
              call r.findnext(critere)
           loop
     
           r.close:set r=nothing
           db.close:set db=nothing
           Concatener=result
        end function
    désolée mais mes compétences ne vont pas jusque là, j'utilise essentiellement le générateur d'expression même si je m'efforce de comprendre aussi les autres types de langage... est-ce que ce code peut être traduit en format "générateur d'expression Access" ?


    Merci beaucoup !

    Nom : xREQetat_PERTURB3.jpg
Affichages : 1415
Taille : 84,9 Ko Nom : xREQetat_PERTURB3result.jpg
Affichages : 1395
Taille : 74,5 Ko

  4. #4
    Membre confirmé
    Femme Profil pro
    Chercheuse Sciences humaines
    Inscrit en
    Juillet 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Chercheuse Sciences humaines

    Informations forums :
    Inscription : Juillet 2014
    Messages : 33
    Par défaut Essai VBA avec DAO
    Bon, pour l'instant ça me paraît incompréhensible mais je veux bien essayer... (j'ai déjà fait des test pour comprendre le VBA mais ça remonte un peu et c'était pas mega fructueux).

    Code de marot_r :

    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
    22
    public function Cancatener(prmTonID as long) as string
           dim result as string
           dim db as dao.database:set db=currentdb
           dim r as dao.recordset:set r=db.openrecordset("reqValeur", dbOpenSnapshot)
           dim critere as string:critere="[TonID]=" & prmTonID
     
           call r.findfirst(critere)
     
           do while not r.nomatch
     
              if result <>"" then
                result=result & "; "
              end if
     
              result=result & r![Valeur]
              call r.findnext(critere)
           loop
     
           r.close:set r=nothing
           db.close:set db=nothing
           Concatener=result
        end function

    1. j'aimerais savoir où je dois placer le code : quand j'ouvre la page Microsoft VBA, seuls les formulaires apparaissent dans l'arborescence de la base de données. Je ne veux pas intervenir sur un formulaire mais dans une requête.

    2. dans le code, que signifient :
    - "reqValeur" (je suppose que c'est le nom de la requête sur la liste de valeurs .Value)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select [TaTable].[TonID], [TaTable].[TYPE_PERTURB].Value as Valeur
    from [TaTable];
    - "prmTonID" et du coup "[TonID]=" & prmTonID ?

    - les autres typo en rouge doivent-elles être modifiées ?

    J'ai regardé un peu de tuto sur VBA mais pas encore assez approfondi... je veux bien quelques pas à pas et liens vers de bonnes pages à lire.

    Merci encore.

  5. #5
    Modérateur

    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    15 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2005
    Messages : 15 437
    Par défaut
    Bonjour.

    Oui j'ai bien compris que les champs multivalués n'étaient pas si bien qu'ils en ont l'air, du moins sont assez trompeurs... bon, mais quand on a besoin de définir plusieurs variables d'un même champ pour un même individu, comment on fait ? plein de champs booléens oui/non ?
    En fait les champs valués sont une table dans une table.

    La méthode habituelle consiste à créer une table d'association, ce n'est pas si différent, mais personnellement je préfères.

    Ici un exemple :

    tblPersonne
    ClefPersonne

    tblEtat
    ClefEtat
    CodeEtat
    DescriptionEtat

    tblEtatPersonne 'table d'association
    ClefEtatPersonne
    ClefPersonne
    ClefEtat

    • En relation avec tblPersonne
    • En relation avec tblEtat


    Cette architecture permet d'avoir autant d'état que voulu pour une personne donnée.

    Note que les désavantages de cette solution sont les suivant :
    1. On ne peut pas présenter les états en colonne côte à côte (comme dans un tableau Excel)
    2. Il peut être moins évident de tester si une personne est dans plusieurs états.
    3. Il faut un peu plus de formulaires pour faire la saisie.


    j'aimerais savoir où je dois placer le code
    La solution la plus simple est de créer un nouveau module et d'y copier le code.
    Pour appeler la fonction dans une requête il faudra faire quelque chose comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    NomTomChampCalcule : Cancatener([TaTable].[TonID])
    - "reqValeur" (je suppose que c'est le nom de la requête sur la liste de valeurs .Value)
    Oui c'est le nom de la requête que tu as créée pour présenter les valeurs.

    - "prmTonID" et du coup "[TonID]=" & prmTonID ?
    • prmTonID est un nom bidon qu'il faut substituer par le nom réel de ton champ dans la requête. Ce n'est pas indispensable mais cela rend les choses plus claires.
      En passant [CODEinline]prm[/CODEinlne] est une abréviation personnelle pour "paramètre" qui me permet de savoir que cette variable vient de l'extérieur de ma fonction.
    • TonID est a remplacer par le nom de ton champ dans la requête.



    J'ai regardé un peu de tuto sur VBA mais pas encore assez approfondi... je veux bien quelques pas à pas et liens vers de bonnes pages à lire.
    Jette un œil au tutoriaux qui sont sur le site (https://access.developpez.com/cours/), le chapitre "Programmation dans Microsoft Access".

    Sinon passe à ta bibliothèque préférée et cherche un truc du genre "Access pour débutant" ou l'équivalent.
    Je reconnais que cela peut être un peu déroutant au départ car il y a pas mal de chose à couvrir pour avoir une vraie application.

    Et n'hésite pas à poser plus de questions.

    A+
    Vous voulez une réponse rapide et efficace à vos questions téchniques ?
    Ne les posez pas en message privé mais dans le forum, vous bénéficiez ainsi de la compétence et de la disponibilité de tous les contributeurs.
    Et aussi regardez dans la FAQ Access et les Tutoriaux Access. C'est plein de bonnes choses.

  6. #6
    Modérateur

    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    15 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2005
    Messages : 15 437
    Par défaut
    J'avais raté ce point.

    comment on fait ? plein de champs booléens oui/non ?
    Là cela dépend un peu. Si ton nombre est fixe est connu, on peut y aller avec un champ par valuer.

    J'ai une table ou j'ai les champs booléens suivant

    • EstIntervention
    • EstEntertient
    • EstSurTemps


    Ce sont les seuls que j'aurai jamais et je les interrogent souvent donc c'est plus efficace et plus simple qu'une table d'association même si pour les 2 1er j'aurai du si j'avais étais stricte crée une table des types et avoir un code de type (intervention ou Entretien).

    A+
    Vous voulez une réponse rapide et efficace à vos questions téchniques ?
    Ne les posez pas en message privé mais dans le forum, vous bénéficiez ainsi de la compétence et de la disponibilité de tous les contributeurs.
    Et aussi regardez dans la FAQ Access et les Tutoriaux Access. C'est plein de bonnes choses.

  7. #7
    Membre confirmé
    Femme Profil pro
    Chercheuse Sciences humaines
    Inscrit en
    Juillet 2014
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Chercheuse Sciences humaines

    Informations forums :
    Inscription : Juillet 2014
    Messages : 33
    Par défaut
    Re bonjour et merci pour tous tes conseils !

    En fait les champs valués sont une table dans une table.
    La méthode habituelle consiste à créer une table d'association, ce n'est pas si différent, mais personnellement je préfères.
    Oui, j'avais saisi cet aspect mais pour la mise en formulaire c'est quand même nettement moins pratique ! Mais bon, je vais m'efforcer pour la suite de faire comme ça... en attendant j'apprends de nouvelles choses aussi avec cette façon de faire.

    Pour ce qui est du code VBA, je reprends tout depuis le début en simplifiant :
    • Dans (TAB_1) j'ai (ID_1) et (Champ_A (Champ_A.Value))
    • Dans une première requête, j'ai isolé les valeurs : (REQ_A-Valeurs)
    • J'ai créé un nouveau module comme suit :
      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
      22
      23
             Public Function Cancatener(prmID_1 As Long) As String
             Dim result As String
             Dim db As dao.Database: Set db = CurrentDb
             Dim r As dao.Recordset: Set r = db.OpenRecordset("REQ_A-Valeurs", dbOpenSnapshot)
             Dim critere As String: critere = "[prmID_1]=" & ID_1
       
             Call r.FindFirst(critere)
       
             Do While Not r.NoMatch
       
                If result <> "" Then
                  result = result & "; "
                End If
       
                result = result & r![Valeur]
                Call r.FindNext(critere)
             Loop
       
             r.Close: Set r = Nothing
             db.Close: Set db = Nothing
             Concatener = result
          End Function
    • Si je comprends bien, je crée une nouvelle requête (REQ_ID1_A-Valeurs) pour appeler ma fonction (code rentré dans le module) dans un nouveau champ, en allant chercher le module créé dans les fonctions de ma base enregistrées, ce qui donne l'expression suivante :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      Concat_TypePerturb: Cancatener(«prmID_1»)


    Le champ («prmID_1») n'existe cependant que dans le code VBA.
    Si je comprends un peu la logique d'Access, il devrait se trouver aussi dans la base pour que le logiciel sache où chercher l'info, non ? Mais où ?
    Est-ce que ce doit être une sorte d'image de (ID_1) dans la première requête (REQ_A-Valeurs) ?
    J'ai essayé mais ça ne donne rien, access me demande d'entrer une valeur de paramètre pour («prmID_1»).



    Pour les lectures, je vais me plonger dans les cours de DVP. J'ai déjà un bouquin sur Access mais le VBA n'y est pas du tout développé. J'ai regardé dans les livres conseillés mais la plupart de ceux qui ont une bonne critique ne sont plus disponibles. Le seul que j'ai trouvé qui semble pas mal pour un niveau "débutant avec des bases" c'est celui-ci . Si vous avez d'autres idées...

    Merci encore !

  8. #8
    Modérateur

    Homme Profil pro
    Inscrit en
    Octobre 2005
    Messages
    15 437
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations forums :
    Inscription : Octobre 2005
    Messages : 15 437
    Par défaut
    Bonjour.

    La 1ère étape c'est de créer la requête qui va te donner les champs multivalués. Si tu l'as fait, poste son SQL. Cela aidera pour la syntaxe.

    Ensuite il faut créer une requête qui va te donner la liste des identifiants, et dans cette requête, créer un champ calculer qui va appeler ta fonction.
    Quelque chose comme :`

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    select [TaTable].[TonID],  Concatener([TaTable].[D_1]) as Concat_TypePerturb from [TaTable]

    Bien que Access soit TRÈS (trop) tolérant sur les noms des objets (tables, requêtes, fonctions, procédures, champs) je recommande se limiter aux chiffres, aux lettres majuscules et minuscules sans accent et sans "décoration" (pas de ç) et au souligné (_). Pas d'espace, de tiret ou autres caractères non alphabétiques.
    Cela évite des bugs vicieux et sournois.

    Si tu as besoin de texte plus agréable pour l'humain, utilise des formulaires et des étiquettes. Ils sont là pour ça.

    Et voici le code modifié.

    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
    22
     Public Function Cancatener(prmID_1 As Long) As String
           Dim result As String
           Dim db As dao.Database: Set db = CurrentDb
           Dim r As dao.Recordset: Set r = db.OpenRecordset("REQ_A-Valeurs", dbOpenSnapshot)
           Dim critere As String: critere = "[ID_1]=" & prmID_1 'On va chercher tous les enregistrements qui ont le ID passé en paramètre.
     
           Call r.FindFirst(critere)
     
           Do While Not r.NoMatch
     
              If result <> "" Then
                result = result & "; "
              End If
     
              result = result & r![Valeur]
              Call r.FindNext(critere)
           Loop
     
           r.Close: Set r = Nothing
           db.Close: Set db = Nothing
           Concatener = result
    End Function
    A+
    Vous voulez une réponse rapide et efficace à vos questions téchniques ?
    Ne les posez pas en message privé mais dans le forum, vous bénéficiez ainsi de la compétence et de la disponibilité de tous les contributeurs.
    Et aussi regardez dans la FAQ Access et les Tutoriaux Access. C'est plein de bonnes choses.

Discussions similaires

  1. Réponses: 11
    Dernier message: 12/08/2010, 15h24
  2. [WSS3] Groupement sur champ multivalué
    Par Ditch dans le forum SharePoint
    Réponses: 6
    Dernier message: 09/04/2008, 09h55
  3. Problème Requête SELECT sur champ texte
    Par arnaud_verlaine dans le forum WinDev
    Réponses: 5
    Dernier message: 02/10/2007, 21h19
  4. Réponses: 5
    Dernier message: 03/11/2005, 16h54
  5. Requête calcul sur champs
    Par tikawua dans le forum Langage SQL
    Réponses: 6
    Dernier message: 12/10/2005, 15h26

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