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 :

Est-il possible d'utiliser la fonction TOP avec un argument variable ?


Sujet :

Requêtes et SQL.

  1. #1
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut Est-il possible d'utiliser la fonction TOP avec un argument variable ?
    Bonjour à tous,

    mon problème, dans Access 2003, s'exprime assez simplement :

    comment ajouter à une table T' les N premiers enregistrements d'une table T où N est une donnée contenue dans le champ p d'une table Paramètre ?

    J'ai testé sans succès le code suivant :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO T_Prime
    SELECT TOP P.p *
    FROM T,P;

    Merci par avance de votre aide !

  2. #2
    Expert éminent
    Avatar de cafeine
    Inscrit en
    Juin 2002
    Messages
    3 904
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 3 904
    Points : 6 781
    Points
    6 781
    Par défaut
    Hello,

    as-tu essayé une imbrication (non testé)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO T_Prime
    SELECT TOP (SELECT P.p FROM P) T.*
    FROM T;
    Sinon c'est faisable en VBA.

    Citation Envoyé par 16-Marco
    Bonjour à tous,

    mon problème, dans Access 2003, s'exprime assez simplement :

    comment ajouter à une table T' les N premiers enregistrements d'une table T où N est une donnée contenue dans le champ p d'une table Paramètre ?

    J'ai testé sans succès le code suivant :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    INSERT INTO T_Prime
    SELECT TOP P.p *
    FROM T,P;

    Merci par avance de votre aide !
    Ne mettez pas "Problème" dans vos titres, par définition derrière toute question se cache un problème
    12 tutoriels Access



  3. #3
    Membre expert
    Avatar de mout1234
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    2 210
    Détails du profil
    Informations personnelles :
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2006
    Messages : 2 210
    Points : 3 228
    Points
    3 228
    Par défaut
    Salut,

    Je ne crois que tu puisses utiliser un paramètre pour la clause TOP... mais rien ne t'empêche de construire à la volée ta commande SQL en VBA.

    Un code du genre (non testé)

    Code vba : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Dim lTop As Long
    Dim sSQL As String
     
    lTop = DLookup("P", "P")
    sSQL = "INSERT INTO T_Prime" & _
            "SELECT TOP " & lTop & " *" & _
            "FROM T"
     
    CurrentDb.Execute sSQL, dbFailOnError
    ............................................................................................

    Dans l'intérêt de tous, ne posez pas de questions techniques par messages privés.

  4. #4
    Rédacteur/Modérateur
    Avatar de loufab
    Homme Profil pro
    Entrepreneur en solutions informatiques viables et fonctionnelles.
    Inscrit en
    Avril 2005
    Messages
    12 004
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Entrepreneur en solutions informatiques viables et fonctionnelles.
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 12 004
    Points : 24 592
    Points
    24 592
    Par défaut
    Bonjour,

    Sous vba créer la requete suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    sql = "INSERT INTO T_Prime 
    SELECT TOP " & dlookup("nom_champ","table_Parametre","condition where valide") & " FROM T;"

    puis faire un

    Le dlookup va chercher le paramètre.

    Cordialement,
    Détecter les modifications formulaire Cloud storage et ACCESS
    Classe MELA(CRUD) Opérateur IN et zone de liste Opérateur LIKE
    Visitez mon Blog
    Les questions techniques par MP ne sont pas lues et je ne pratique pas la bactériomancie

  5. #5
    Membre averti Avatar de mcdotta
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    292
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mai 2005
    Messages : 292
    Points : 324
    Points
    324
    Par défaut
    Hello,


    Oui, mais à mon avis il faut passer par du code VBA

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Dim i as integer
    Dim strSQL as string
     
    i = CInt(DLookup("[p]","P"))
     
    strSQL = "INSERT INTO T_Prime
    strSQL = strSQL & " SELECT TOP " &  i & " *"
    strSQL = strSQL & " FROM T"
     
    CurrentDb.Execute strSQL
    Attention : j'ai saisi le code directement ici dont il n'a pas été testé....

  6. #6
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    merci pour vos réponses

    Je vais étudier les faq et autres tutoriels ayant trait à VBA dans Access (j'imagine qu'il faut passer par un module) et reviendrai cloturer la discussion dès que j'ai trouvé

  7. #7
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par mcdotta
    Hello,


    Oui, mais à mon avis il faut passer par du code VBA

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Dim i as integer
    Dim strSQL as string
     
    i = CInt(DLookup("[p]","P"))
     
    strSQL = "INSERT INTO T_Prime
    strSQL = strSQL & " SELECT TOP " &  i & " *"
    strSQL = strSQL & " FROM T"
     
    CurrentDb.Execute strSQL
    Attention : j'ai saisi le code directement ici dont il n'a pas été testé....
    merci à toi : ton code marche !
    Bye

  8. #8
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par mcdotta
    Hello,


    Oui, mais à mon avis il faut passer par du code VBA

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Dim i as integer
    Dim strSQL as string
     
    i = CInt(DLookup("[p]","P"))
     
    strSQL = "INSERT INTO T_Prime
    strSQL = strSQL & " SELECT TOP " &  i & " *"
    strSQL = strSQL & " FROM T"
     
    CurrentDb.Execute strSQL
    Attention : j'ai saisi le code directement ici dont il n'a pas été testé....
    Je reviens en fait sur le sujet pour l'enrichir d'une question :

    En réalité dans ma table T j'ai par exemple 100 enregistrements de 2 familles : 75 de la famille A suivis de 25 de la famille B.

    Dans ma table de paramètre P j'ai 2 valeurs pour mon paramètre: pour chaque famille A et B j'ai le nombre de lignes que je dois extraire à partir de la table T, respectivement dans les familles A et B, par exemple 6 et 10

    Comment modifier l'instruction ci-dessus pour extraire du même coup les 6 premières enre. de la table qui sont de famille A (autrement dit les lignes 1 à 6) et les 10 premiers enre. qui sont de la famille B (autrement dit les lignes 76 à 85) ?

    Merci!

  9. #9
    Expert confirmé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 419
    Points : 4 297
    Points
    4 297
    Par défaut
    si j'ajoute cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Function garde(famille As String, nb As Long) As Boolean
    Static fam As String
    Static compteur As Long
    If fam = famille Then
       compteur = compteur + 1
       Else
       fam = famille
       compteur = 1
    End If
    garde = compteur <= nb
    End Function
    la requête suivante
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT matable.famille, 
    matable.valeur
    FROM matable INNER JOIN param 
    ON matable.famille = param.famille
    WHERE garde([matable].[famille],[nb])=True
    ORDER BY matable.famille, matable.valeur;

    devrait donner satisfaction
    nb la clause order by famille en première clef de tri est indispensable

    nb on peut réinitialiser en faisant un appel à garde("zwchpountz";123)
    Elle est pas belle la vie ?

  10. #10
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    merci random,
    mais question bête : j'ai créé la fonction garde dans un module, puis la requête en rentrant le code SQL.
    Par contre je n'arrive pas à l'exécuter : je reçois le message

    "fonction garde non définie dans l'expression".

    Quelle fausse manip ai-je faite ?

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Mai 2005
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 419
    Points : 4 297
    Points
    4 297
    Par défaut
    copie nous ton sql
    Elle est pas belle la vie ?

  12. #12
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    autant pour moi : j'avais intitulé mon module du même nom que la fonction que tu proposais.

    Le tout marche très bien et évite de passer par des créations de table.

    En résumé :

    dans un module créer la fonction garde décrite ci-dessus. Donner au module un nom différent de "garde"

    dans la vue requete, créer une requete avec le code sql proposé.

    s'assurer que la table "matable" soit déjà bien classée pour obtenir le résultat souhaité (la clause order by est à mon sens un luxe)

    Cette requete permet de n'afficher que les X premières lignes de chaque ensemble d'enregistrements de "matable", identifiés par le critère "famille"
    Merci beaucoup

  13. #13
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    Je recreuse encore le problème !
    En réalité la sélection des x 1eres lignes ne se fera pas sur 1 seul critère (la famille), mais sur plusieurs :

    "matable" ressemblera donc à :
    famille1
    famille2
    valeur

    "param" ressemblera donc à :
    famille1
    famille2
    nombre lignes à selectionner dans "matable" lorsque les 2 critères matchent.

    j'ai modifié de la façon suivante le code de la fonction :
    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
    Function gardemarc(famille1 As String, famille2 As String, nb As Long) As Boolean
     
    Static fam1 As String
    Static fam2 As String
    Static compteur As Long
    If fam1 = famille1 Then
       If fam2 = famille2 Then
       compteur = compteur + 1
            Else
            fam1 = famille1
            fam2 = famille2
            compteur = 1
        End If
        Else
        fam1 = famille1
        fam2 = famille2
        compteur = 1
    End If
    garde = compteur <= nb
    Exit Function
    End Function
    et la requête sql:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT matable.famille1, matable.famille2, matable.valeur
    FROM matable INNER JOIN param ON (matable.famille1=param.famille1) AND( matable.famille2=param.famille2)
    WHERE gardemarc([matable].[famille1],[matable].[famille2],[param])=True
    ORDER BY matable.famille1, matable.famille2;
    Pour autant j'ai le message d'erreur à l'execution de la requête :
    "erreur de compilation dans l'expression gardemarc([matable].[famille1],[matable].[famille2],[param])=True

    Quelqu'un sait pourquoi ?
    merci d'avance !

  14. #14
    Candidat au Club
    Inscrit en
    Février 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 11
    Points : 2
    Points
    2
    Par défaut
    Citation Envoyé par random
    si j'ajoute cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Function garde(famille As String, nb As Long) As Boolean
    Static fam As String
    Static compteur As Long
    If fam = famille Then
       compteur = compteur + 1
       Else
       fam = famille
       compteur = 1
    End If
    garde = compteur <= nb
    End Function
    la requête suivante
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT matable.famille, 
    matable.valeur
    FROM matable INNER JOIN param 
    ON matable.famille = param.famille
    WHERE garde([matable].[famille],[nb])=True
    ORDER BY matable.famille, matable.valeur;

    devrait donner satisfaction
    nb la clause order by famille en première clef de tri est indispensable

    nb on peut réinitialiser en faisant un appel à garde("zwchpountz";123)

    Hello again
    question subsidiaire : ceci marche impec à partir d'une table, par contre si je remplace la table par une requête R issue de plusieurs calculs, et à la base de tables, j'ai beau trier comme je le souhaite l'affichage de R, la fonction n'extrait pas toujours les bonnes lignes car elle semble ignorer le tri 'artificiel' que j'ai mis dans ma requête R...ça m'embête drolement car cela signifie qu'à chaque fois que je vais devoir utiliser la fonctionnalité garde il va falloir passer par une table temporaire..A moins qu'il n'y ait une parade ?
    Thanks again !

Discussions similaires

  1. Réponses: 8
    Dernier message: 07/02/2012, 08h03
  2. Réponses: 2
    Dernier message: 02/01/2012, 22h23
  3. Réponses: 6
    Dernier message: 24/03/2011, 09h08
  4. Réponses: 1
    Dernier message: 02/12/2010, 23h26
  5. Réponses: 0
    Dernier message: 23/08/2007, 15h42

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