none
Sélection SQL RRS feed

  • Question

  • Bonsoir,

    Je voudrais réaliser une requête SQL pour sélectionner les auteurs (colonne Auteur) d'articles constituants les enregistrements de la table Livres.

    La requête "SELECT Auteur FROM Livres" fonctionne bien mais les auteurs apparaissent plusieurs fois s'ils ont écrit plusieurs articles.

    Quelle requête écrire pour n'obtenir qu'une seule occurrence par auteur ?

    voici le code que j'ai écrit :

                    // Commande : Sélectionner TOUS les Auteurs
                    IDbCommand cmd = "SELECT Auteur FROM Livres"; 
    
                    // Enumérer les enregistrements lus
                    IDataReader lect = cmd.ExecuteReader();
                    while (lect.Read())
                    {
                        // Créer un enregistrement dans la table
                        DataRow dr = ListeAuteurs.NewRow();
                        dr["Actuels"] = lect.GetValue(0).ToString();
                        dr["Remplacement"] = "";
                        ListeAuteurs.Rows.Add(dr);
                    }
    

    Evidemment je pourrais filtrer après le  lect.GetValue(0).ToString()

    Mais j'aurais préféré une solution plus élégante...

    Merci de vos suggestions.

    Cordialement


    Alain

    lundi 27 janvier 2014 23:54

Réponses

  • Bonjour,

    SELECT DISTINCT Auteur FROM Livres

    ou alors

    SELECT Auteur FROM Livres GROUP BY Auteur

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    • Marqué comme réponse AchLog mercredi 29 janvier 2014 12:34
    mercredi 29 janvier 2014 00:27
    Modérateur

Toutes les réponses

  • Bonjour,

    SELECT DISTINCT Auteur FROM Livres

    ou alors

    SELECT Auteur FROM Livres GROUP BY Auteur

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    • Marqué comme réponse AchLog mercredi 29 janvier 2014 12:34
    mercredi 29 janvier 2014 00:27
    Modérateur
  • Merci beaucoup Gilles,

    Je pense que DISTINCT joue en début de sélection alors que le GROUP BY est plutôt un post traitement.

    En terme de temps de réponse, y-a-t'il une différence ?

    Bien cordialement.


    Alain

    mercredi 29 janvier 2014 09:22
  • Bonjour

    Il n'y a pas une grande différence.
    Ça dépend de moteur SQL et l'existence des index sur cette colonne.
    D’habitude on préfère de utiliser une table Auteurs (AuteurId INT, Nom varchar(500))
    Et une autre table Article (ArticleId int, AuteurId int, Titre varchar(100).......)
    Comme ça on réduit la possibilité d’avoir deux fois le même auteur à cause d’une différence d’écriture du nom (par exemple Jean Luc Piccard et Jean-Luc Piccard).
    En plus le GROUP by et DISTINCT sont plus rapides sur des colonnes INT que sur des VarChar.

    Cordialement


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mercredi 29 janvier 2014 11:44
  • Merci beaucoup, Gilles, pour ces précisions fort utiles.

    Bien cordialement

    P.S. Je profite de cet échange pour vous dire tout le bien que je pense de votre bouquin "C# L'essentiel du code et des classes". J'ai souvent recours à lui (bien qu'ici il soit resté muet !). 


    Alain

    mercredi 29 janvier 2014 12:34
  • Juste une petite question supplémentaire :

    Suite à la modification suivante de la table "Livres" :

    "UPDATE [Livres] SET Auteur = '" + NewValue + "' WHERE Auteur = '" + Original + "';"

    je voudrais "récupérer" tous les enregistrements qui ont été modifiés par cette commande.

    Existe-il une requête SQL qui ferait cela ?

    Merci beaucoup.

    Cordialement


    Alain

    mercredi 29 janvier 2014 20:58
  • Bonjour,

    Si vous êtes sous SQL Server vous pouvez utiliser la clause OUTPUT dans la commande UPDATE.

    UPDATE Livres
    SET Auteur = @newValue
    OUTPUT deleted.Auteur AS OldAuteur, inserted.Auteur AS NewAuteur
    WHERE Auteur = @original
    

    Utilisez si possible les requêtes SQL paramétrées (via le caractère "@") qu'il suffit d'alimenter via la propriété Parameters de votre objet SqlCommand.

    Ce genre de requête vous retourne une table avec l'ancien auteur et le nouvel auteur modifié. Pour récupérer le résultat de cette requête, il ne faut pas l'exécuter via la méthode ExecuteNonQuery() mais via ExecuteReader() afin de lire ligne par ligne le résultat de la requête.

    Est-ce que cela répond à votre question ?

    P.S. Je profite de cet échange pour vous dire tout le bien que je pense de votre bouquin "C# L'essentiel du code et des classes". J'ai souvent recours à lui (bien qu'ici il soit resté muet !).
    Merci...

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    jeudi 30 janvier 2014 01:21
    Modérateur
  • Merci Gilles pour votre réponse.

    Le programme porte sur une base de données Access, non SQL Serveur et, dans mon code actuel (qui n'est surement pas au top) il n'y a pas d'objet SqlCommand ! Je ne demande qu'à apprendre comment faire...

    Voici ce code, très simple :

                                // Appliquer le remplacement de chaque occurrence de l'Original
                                string SQLmaj = "UPDATE [Livres] SET Auteur = '" + NewValue
                                                + "' WHERE Auteur = '" + Original + "';";
    
                                OleDbCommand cmde = new OleDbCommand(SQLmaj, cnn);
                                cmde.ExecuteNonQuery();

    Je le remplace, au moins provisoirement (mais je suis preneur d'une meilleure solution) en suivant vos indications par celui-ci :

    IDbCommand cmd = cnn.CreateCommand(); cmd.CommandText = "UPDATE [Livres] SET Auteur = '" + NewValue; cmd.CommandText += "' OUTPUT deleted.Auteur AS OldAuteur, inserted.Auteur AS NewAuteur"; cmd.CommandText += " WHERE Auteur = '" + Original + "';"; // Enumérer les enregistrements Modifiés ListeModifs.Clear(); IDataReader lect = cmd.ExecuteReader(); while (lect.Read()) { // Créer un enregistrement dans cette table DataRow r = ListeModifs.NewRow(); r["Old"] = lect.GetValue(0).ToString(); r["New"] = lect.GetValue(1).ToStrong();

    ListeModifs.Rows.add(r);

    }

    En relisant à nouveau votre réponse, j'ai cru comprendre que OldAuteur et NewAuteur étaient les noms des champs de la table retournée par la requête...

    je l'ai réécrite de la façon suivante, sans succès à l'exécution :

                                // New Requête
                                string OldAuteur = "Old";
                                string NewAuteur = "New";
    
                                IDbCommand cmd = cnn.CreateCommand();
                                cmd.CommandText =  "UPDATE [Livres] SET Auteur = '" + NewValue
                                                 + "' OUTPUT deleted.Auteur AS '" + OldAuteur + "', inserted.Auteur AS '" + NewAuteur + "'"
                                                 + " WHERE Auteur = '" + Original + "';";
    
                                // Enumérer les enregistrements Modifiés
                                IDataReader lect = cmd.ExecuteReader();
    

    Est-ce une incompatibilité ACCESS ou une erreur dans la requête ?

    Merci de votre réponse.

    Bien cordialement


    Alain



    • Modifié AchLog jeudi 30 janvier 2014 13:18 Complément
    jeudi 30 janvier 2014 10:18
  • Bonjour,

    Access ne prend pas en charge la clause OUTPUT...

    Vous devez donc exécuter une requête SELECT avant pour connaître la liste des lignes que vous allez modifier...

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    jeudi 30 janvier 2014 23:06
    Modérateur
  • Ok, merci.

    Dommage !

    Cordialement


    Alain

    vendredi 31 janvier 2014 09:04
  • Question subsidiaire :

    Quel rapport y-a-t'il entre un programme C# indépendant comme le mien, qui se connecte à une base *.mdb, d'une part, et ACCESS d'autre part ?

    Autrement dit, quel serveur intervient ici ? ACCESS est effectivement installé sur ma machine de développement, mais est-il indispensable à la connexion?

    Merci de votre réponse

    Cordialement


    Alain

    vendredi 31 janvier 2014 09:10
  • Bonjour,

    Votre application C# se connecte au moteur Access via un runtime. Ce runtime est installé bien évidemment avec Access mais on peut aussi le télécharger gratuitement sur le site de Microsoft afin de l'utiliser sur des postes où Access n'est pas utilisé.

    Sans ce runtime, votre application C# ne peut se connecter à une base de données Access. Attention, Access n'est pas un serveur de données... Les bases de données Access sont juste des fichiers qui sont exploités par un runtime...

    Pour téléchargement le runtime :

    http://www.microsoft.com/fr-fr/download/details.aspx?id=39358

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    lundi 3 février 2014 00:54
    Modérateur
  • Merci Gilles de ces précisions.

    Il serait alors pratique que ce runtime fasse partie des prérequis du déploiement ClickOnce pour être téléchargé automatiquement comme ceux-ci s'il est absent de la machine cible.

    Est-ce possible dans un déploiement ClickOnce et, si oui, comment faire ?

    Cordialement


    Alain

    lundi 3 février 2014 13:17
  • Bonjour,

    Il est possible de créer des package de pré-requis pour ClickOnce. Regardez la documentation Microsoft pour plus d'informations : http://msdn.microsoft.com/en-us/library/ms165429.aspx

    Cordialement


    Gilles TOURREAU - MVP C#
    Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
    Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
    - MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
    - MCSA : SQL Server 2012
    - MCITP : SQL Server 2008 Developper
    - MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure

    lundi 3 février 2014 23:51
    Modérateur
  • Merci Gilles. Je regarde.

    Bien cordialement


    Alain

    mardi 4 février 2014 06:41