1. #1
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    juillet 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : juillet 2017
    Messages : 16
    Points : 8
    Points
    8

    Par défaut Sélectionner des lignes d'une table contenant une valeur présente dans une autre table [Débutant]

    Bonjour,

    3 questions en une cette fois !
    J'avance dans la conversion de mon programme de VBA vers VB.Net, mais je bute encore ici.

    Voici le pb auquel je suis confronté:
    Table1 est une table access.
    Je veux sélectionner les lignes de Table1 correspondant aux strTech (technologies) de Ent1 (Entreprise1).

    strEntr_____strTech_____Num1_____Num2
    Ent1________Tech1______ 12_______ 15
    Ent1________Tech3_______10_______ -5
    Ent1________Tech4_ ______ 4 ________-6

    Ent2________Tech1_______13________14
    Ent2________Tech2_______12________15

    Ent3________Tech2_______14________11
    Ent3________Tech4________2_________-3

    Dans cet exemple, Ent1 utilise les technologies 1, 3 et 4 donc je voudrais retenir les lignes où strTech vaut 1, 3 ou 4 (dans cet exemple on retient donc les lignes 1;2;3;4;7 de la table).

    J'avais donc pensé à :
    a) Créer une table contenant les valeurs de strTech recherchées.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    strSql = "SELECT Table1.strTech FROM Table1 " _
                   & " WHERE Table1.strEnt = " & "'" & strEntRetenue  & "'"
     
    ObjetCommand = New OleDbCommand(strSql)
    ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)
    ObjetCommand.Connection() = ObjetConnection
    ObjetDataAdapter.Fill(ObjetDataSet, "Table2")
    ObjetDataTableJCible = ObjetDataSet.Tables("Table2")
    Je pensais avoir ainsi créé une table 'Table2' contenant une seule colonne (strTech) et en ligne uniquement les technologies utilisées par Entreprise1: Tech1; Tech3; Tech4.
    En effet:
    _____i)L'exécution du Data Reader me confirme que Table2 contient bien les données attendues
    ____ ii)La fenêtre Variables Locales me confirme que ObjetDataTable2 contient bien une table de nom "Table2" (ObjetDataTable2.EncodedTableName= "Table2".

    b) Faire un SELECT sur table1 en ne retenant que les strTech présentes dans Table2..
    Mais lorsque je lance la 2è étape:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    strSql2 = "SELECT Table1.* FROM Table1 " _
                                        & " WHERE Table1.strTECH IN (SELECT Table2.StrTECH FROM Table2)"
     
     
    ObjetCommand2 = New OleDbCommand(strSql2)
    ObjetDataAdapter2 = New OleDbDataAdapter(ObjetCommand2)
    ObjetCommand2.Connection() = ObjetConnection
    ObjetDataAdapter2.Fill(ObjetDataSet2, "Table")
    ObjetDataTable2 = ObjetDataSet2.Tables("Table")
    J'obtiens l'erreur suivante sur la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ObjetDataAdapter2.Fill(ObjetDataSet2, "Table")
    "L'exception de base de données Microsoft Jet n'a pas été gérée. Le moteur de base de données Microsoft Jet ne peut pas trouver la table ou la requête source Table2. Assurez-vous qu'elle existe et qu'elle correctement orthographiée."

    Ainsi mes questions:
    I. (hormis défaut de syntaxe) j'ai l'impression que cela signifie que l'étape I n'a pas créé de table 'Table2" (en tous cas pas qui puisse être appelée dans un SELECT).

    Ainsi ObjetDataAdapter.Fill ne crée pas de table à laquelle le programme peut accéder ?!?

    II. Création de table
    Du coup je me retrouve au dépourvu et me demande comment je peux réellement créer une table supplémentaire en VB.NET à partir d'un SELECT, quitte à effacer cette table temporaire en fin de programme.
    En SAS par exemple j'ai souvenir que ct assez simple. Une Proc CREATE et hop la table était créée.

    III. Existe-t-il une méthode astucieuse pour réaliser en une étape (juste avec le SELECT de a.) les 2 opérations, sans avoir à créer une table annexe contenant les seules strTech recherchées?

    III. Non optimisation de mon algo
    Cela me rappelle que, en toute fin d'algo, je met certes à jour ma table Table1, mais c'est avec une méthode un peu laborieuse:
    Je rajoute des lignes une par une à Table1 par la méthode:
    For i=1 to 1.000
    ObjetDataRow = ObjetDataSet1.Tables("NomTable").NewRows()

    ObjetDataRow("Variable1")=Matrice(i,1)
    ...
    ObjetDataRow("Variable30")=Matrice(i,30)

    ...
    ObjetDataSet1.Tables("Table1").Rows.Add(ObjetDataRow1)
    ObjetCommandBuilder1 = New OleDbCommandBuilder(ObjetDataAdapter1)
    ObjetDataAdapter1.Update(ObjetDataSet1, "Table1")
    Next i
    (Méthode trouvée sur un tuto dispo sur le site)

    Cette méthode est particulièrement lente, pour créer ma base (elle contient 3 tables: une de 1.000 lignes, une de 50.000 et 1 de 100.000), cela met plus d'heure.
    Bien sûr, une fois la base créée, ce ne sont que qq lignes que je rajoute à la base à chaque mise à jour des données sources et du coup en ce cas l'ajout de lignes une par une a du sens. Mais au premier run (pour refaire la base après correction d'un bug ou ajout d'une fonctionnalité, bam ca fait 1h où le pc est bloqué).

    Ma méthode est probablement à la masse
    (StringBuilder m'avait déjà fait remarquer une erreur de conception comparable de mon algo, me faisant remarquer que sql n'est pas fait pour faire du "cellule par cellule" mais des calculs sur des masses de données.
    Peut être est-ce ici le même pb?

    Au plaisir de vous lire !
    PS: je vous garantis que je passe bcp de tps à essayer de trouver la réponse par moi même ou via les tutos et le net mais franchement j'en bave pour ce passage de VBA à VB.Net/SQL/ACCESS

  2. #2
    Membre expérimenté
    Homme Profil pro
    Développeur .Net et Delphi
    Inscrit en
    juillet 2002
    Messages
    641
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .Net et Delphi
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2002
    Messages : 641
    Points : 1 460
    Points
    1 460

    Par défaut

    Bonjour,

    Je ne connais pas Access mais pour répondre à ta deuxième question, il est inutile en SQL de créer une table temporaire dans ton cas. Tu peux très bien requêter plusieurs fois dans une même table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Table1.* FROM Table1 WHERE Table1.strTECH IN (SELECT Table1.StrTECH FROM Table1 WHERE Table1.strEnt = @Code)
    Concernant la question 3, je ne sais pas ce que contient Matrice ni même comment celle-ci est construite, donc... désolé ;-)

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    juillet 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : juillet 2017
    Messages : 16
    Points : 8
    Points
    8

    Par défaut

    Citation Envoyé par b4ruk Voir le message
    III. Existe-t-il une méthode astucieuse pour réaliser en une étape (juste avec le SELECT de a.) les 2 opérations, sans avoir à créer une table annexe contenant les seules strTech recherchées?
    Citation Envoyé par ebastien Voir le message
    Bonjour,

    Je ne connais pas Access mais pour répondre à ta deuxième question, il est inutile en SQL de créer une table temporaire dans ton cas. Tu peux très bien requêter plusieurs fois dans une même table :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT Table1.* FROM Table1 WHERE Table1.strTECH IN (SELECT Table1.StrTECH FROM Table1 WHERE Table1.strEnt = @Code)
    Concernant la question 3, je ne sais pas ce que contient Matrice ni même comment celle-ci est construite, donc... désolé ;-)
    Merci bcp bastien, cela répond complètement à mon problème !

    Sais-tu pourquoi le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    strSql = "SELECT Table1.strTech FROM Table1 " _
                   & " WHERE Table1.strEnt = " & "'" & strEntRetenue  & "'"
     
    ObjetCommand = New OleDbCommand(strSql)
    ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)
    ObjetCommand.Connection() = ObjetConnection
    ObjetDataAdapter.Fill(ObjetDataSet, "Table2")
    ObjetDataTableJCible = ObjetDataSet.Tables("Table2")
    ne crée pas une Table2 que je puisse appeler dans un SELECT ? Cela m'intrigue tout de même!

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    juillet 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : juillet 2017
    Messages : 16
    Points : 8
    Points
    8

    Par défaut

    Citation Envoyé par b4ruk Voir le message
    Merci bcp bastien, cela répond complètement à mon problème !

    Sais-tu pourquoi le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    strSql = "SELECT Table1.strTech FROM Table1 " _
                   & " WHERE Table1.strEnt = " & "'" & strEntRetenue  & "'"
     
    ObjetCommand = New OleDbCommand(strSql)
    ObjetDataAdapter = New OleDbDataAdapter(ObjetCommand)
    ObjetCommand.Connection() = ObjetConnection
    ObjetDataAdapter.Fill(ObjetDataSet, "Table2")
    ObjetDataTableJCible = ObjetDataSet.Tables("Table2")
    ne crée pas une Table2 que je puisse appeler dans un SELECT ? Cela m'intrigue tout de même!
    Hello Bastien,
    je reviens sur mon avis.
    Je comprends la syntaxe que tu utilises, je l'ai répliquée.
    Elle donne les résultats attendus.
    MAIS!!!! Elle met mon ordinateur à genou dès que la base grandit un peu. Cela devient rapidement ingérable, le PC ne finit pas cette opération de deux SELECT imbriqués.

    J'ai donc opté pour la solution en deux étapes:
    1. Je construis une liste contenant les strTech recherchés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    SELECT Table1.StrTECH FROM Table1 WHERE Table1.strEnt = EntrepriseRetenue
    ...
    Avec un DataReader je lis toutes les lignes et je réalise une chaine de caractères " 'Tech1', 'Tech2', 'Tech4'".
    2. Je lance le SELECT désiré
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    SELECT Table1.* FROM Table1 WHERE Table1.strTECH IN (" & str1 & ")
    Et là le temps de calcul est divisé par deux lorsque la table est petite, puis par 10....
    Je pense donc que l'imbrication de deux boucles SELECT est à réserver aux petites tables.

  5. #5
    Membre éclairé Avatar de star
    Homme Profil pro
    .
    Inscrit en
    février 2004
    Messages
    707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Corée Du Nord

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : février 2004
    Messages : 707
    Points : 848
    Points
    848

    Par défaut

    De par mes connaissances littéraires du SQL en terme d'optimisation, il vaut toujours mieux privilégier EXISTS et NOT EXISTS au IN et NOT IN.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT T1.* FROM Table1 as T1 WHERE EXISTS (SELECT 'x' FROM Table1 as T2 WHERE T2.strTECH = T1.strTECH AND T2.strEnt = @Code)
    .
    Pour la défense de nos droits, merci de voter pour : https://connect.microsoft.com/Visual...wupdated-event
    together we stand, divided we fall
    .

  6. #6
    Membre expérimenté
    Homme Profil pro
    Développeur .Net et Delphi
    Inscrit en
    juillet 2002
    Messages
    641
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur .Net et Delphi
    Secteur : Finance

    Informations forums :
    Inscription : juillet 2002
    Messages : 641
    Points : 1 460
    Points
    1 460

    Par défaut

    Citation Envoyé par star Voir le message
    De par mes connaissances littéraires du SQL en terme d'optimisation, il vaut toujours mieux privilégier EXISTS et NOT EXISTS au IN et NOT IN.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT T1.* FROM Table1 as T1 WHERE EXISTS (SELECT 'x' FROM Table1 as T2 WHERE T2.strTECH = T1.strTECH AND T2.strEnt = @Code)
    .
    C'est vrai, bien vu, EXISTS est plus efficace.

    Je pense donc que l'imbrication de deux boucles SELECT est à réserver aux petites tables.
    Ca dépend du type de base. J'ai déjà créé des requêtes de plus 100 lignes avec imbrications de 6 ou 7 requêtes dont certaines analytiques attaquant des tables de plusieurs milions d'enregistrement mais ... sous Oracle. Je ne crois pas qu'Access soit vraiment conseillé pour de gros volumes.

    Maintenant comment as-tu défini tes index sur ta table ?

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    juillet 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : juillet 2017
    Messages : 16
    Points : 8
    Points
    8

    Par défaut

    Citation Envoyé par ebastien Voir le message
    C'est vrai, bien vu, EXISTS est plus efficace.



    Ca dépend du type de base. J'ai déjà créé des requêtes de plus 100 lignes avec imbrications de 6 ou 7 requêtes dont certaines analytiques attaquant des tables de plusieurs milions d'enregistrement mais ... sous Oracle. Je ne crois pas qu'Access soit vraiment conseillé pour de gros volumes.

    Maintenant comment as-tu défini tes index sur ta table ?
    La colonne d'indexation est automatique (1 2 3 ..)

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Lycéen
    Inscrit en
    juillet 2017
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : juillet 2017
    Messages : 16
    Points : 8
    Points
    8

    Par défaut

    Citation Envoyé par ebastien Voir le message
    C'est vrai, bien vu, EXISTS est plus efficace.



    Ca dépend du type de base. J'ai déjà créé des requêtes de plus 100 lignes avec imbrications de 6 ou 7 requêtes dont certaines analytiques attaquant des tables de plusieurs milions d'enregistrement mais ... sous Oracle. Je ne crois pas qu'Access soit vraiment conseillé pour de gros volumes.
    On m'a effectivement fait la remarque de la "médiocrité" de ACCESS.
    Je prends donc le parti de continuer à développer mon algo, le faire travailler sur un volume de données qui va commencer à augmenter, et je passerai probablement à une autre solution.

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/03/2011, 10h24
  2. Réponses: 5
    Dernier message: 04/12/2008, 16h58
  3. Recherche d'une valeur présent dans une table mais pas dans une autre
    Par bossLINDROS dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 19/06/2008, 16h12
  4. [VBA] fonction qui donne la valeur présente dans une table
    Par zanou666 dans le forum VBA Access
    Réponses: 7
    Dernier message: 25/09/2007, 18h33
  5. Réponses: 4
    Dernier message: 22/03/2007, 19h28

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