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 Delphi Discussion :

Select Distinct dans clientDataset


Sujet :

Langage Delphi

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut Select Distinct dans clientDataset
    Resalut, c'est moi avec mon fameux fichier de 3 millions de lignes.

    Donc j'ai choisie de faire plusieurs test pour voir le plus optimum (utilisation, developpemnt, suivi, évolution etc...) si j'insiste sur ce fameux fichier c'est que je peut en avoir un toutes les mois voir plusieurs fois par mois

    Le permier je passe par un Tclientdataset
    ne fait pas attention à la répétitivité de giveoccurence, cela va changer
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
     
    //*****************************************************************************
    procedure TFrame3.CharegInDataSet(Sender: TObject);
    var
    QaysLogTrace:TQaysLogTrace;
    i:integer;
    begin
      ClientDataSetimport :=TClientDataSet.Create(nil);
      ClientDataSetimport.FieldDefs.Add('operateur',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('operateurcode',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('date-debut',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('date-fin',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('prefix',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('tarif-jour',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('heure-debut',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('heure-fin',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('prix',ftString,30,false);
      ClientDataSetimport.FieldDefs.Add('destination	fichiers',ftString,30,false);
      ClientDataSetimport.CreateDataSet;
      with MigrationFormule do
      begin
    //*************************************************
    //Lecture du max de chaque table pour le numéroteur
    //*************************************************
    //******************************************************************************
        if MigrationFormule.QLFICHIER.ReadFichier = 0 then
        begin
          ProgressBar1.Min := 0;
          ProgressBar1.Max := MigrationFormule.QLFICHIER.GetSize;
     
          GaugeCtrlFic.MinValue:= 0;
          GaugeCtrlFic.MaxValue:=  ProgressBar1.Max;
          i:= 0;
     
          Repeat
            Try
              i:= i+1;
              MigrationFormule.QLFICHIER.ReadLigne;
              GaugeCtrlFic.Progress := i;
              ProgressBar1.Position := i;
              if (i mod 1000)= 0 then begin
                  LabelTimeToExport.Caption := IntToStr(i);
                  Application.ProcessMessages;
              end;
              TempWork.LigneProgress:=MigrationFormule.QLFICHIER.Ligne;
              ClientDataSetimport.Append;
              ClientDataSetimport.FieldByName('operateur').value:=TempWork.GiveOccurence(1);
              ClientDataSetimport.FieldByName('operateurcode').value:=TempWork.GiveOccurence(2);
              ClientDataSetimport.FieldByName('date-debut').value:=TempWork.GiveOccurence(3);
              ClientDataSetimport.FieldByName('date-fin').value:=TempWork.GiveOccurence(4);
              ClientDataSetimport.FieldByName('prefix').value:=TempWork.GiveOccurence(5);
              ClientDataSetimport.FieldByName('tarif-jour').value:=TempWork.GiveOccurence(6);
              ClientDataSetimport.FieldByName('heure-debut').value:=TempWork.GiveOccurence(7);
              ClientDataSetimport.FieldByName('heure-fin').value:=TempWork.GiveOccurence(8);
              ClientDataSetimport.FieldByName('prix').value:=TempWork.GiveOccurence(9);
              ClientDataSetimport.FieldByName('destination	fichiers').value:=TempWork.GiveOccurence(10);
              ClientDataSetimport.Post;
            Except
                on E: Exception do
                begin
                  QaysLogTrace:=TQaysLogTrace.Create;
                  QaysLogTrace.NomAppelant:='TraitementGeneralGrilleRecord';
                  QaysLogTrace.LogDateTime:=(now);
                  QaysLogTrace.Parametre.Add('Erreur :'+E.Message);
                  QaysLogTrace.Parametre.Add(TempWork.LigneProgress);
                  QaysLogTrace.WriteLogTrace;
                end;
            End;
          Until (MigrationFormule.QLFICHIER.FinFichier);
          MigrationFormule.QLFICHIER.CloseFichier;
        end;
      end;
      //*********************************************************
    end;
    Je rempli donc mon clientdataset avec ce fichier de 3millions de lignes ~3 minutes

    maintenant comment faire un select distinct

    sachant que la syntaxe est ;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select distinct from TABLE
    comment le faire dans mon clientdataset car la je n'ai pas de notion de table.

    alors comment je peux faire si cela est possible

    j'ai trouvé ce post:

    http://www.developpez.net/forums/d21...clientdataset/

    mais je ne suis pas sure de comprendre,

    en fait je fait une liaison en un Tprovider =>Tquery et ensuite mon TclientDataset, cela veut dire que je peut faire n'importe quel requete sur mon client dataset ?????????
    Merci de votre patience et compréhension
    Cordialement
    Qays

  2. #2
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    comment faire un select distinct
    La réponse est dans la question, par la syntaxe, c'est un SGBDR supportant SQL.
    Je vais te répondre autrement, quel est l'interêt d'utiliser un Dataset ?

    Tous les composants visuels orientés données ont comme propriété un Datasource qui lui même à comme propriété un composant dont la classe mère est TDataset.
    Donc, si on veut affiché les données dans les composants visuels fournis dans la VCL, on doit avoir des sources de données compatibles avec TDataset, c'est du pur polymorphisme.
    Si on ne veut pas afficher les données graphiquements (ie Batch) on peut utiliser autre chose qu'un déscendant de TDataset.
    Comme les Api de bas niveau des bases de données sont plus performantes que les Datasets et que tu n'as pas besoin d'afficher les données et qu'en plus ton chef n'en veut pas, tout est dit.

    Je récapitule le cahier des charges du chef:

    - Accès au données performant (API bas niveau>Dataset)
    - pas de Dataset
    - Batch: pas besoin d'afficher les données graphiquement => pas besoin de Dataset

    Tes souhaits, un équivalent "Select distinct ..." => SGBDR = language SQL.

    N'essaye pas de réinventé la roue puisque que tu as des logiciels(ie SGBDR) qui le font très bien et gratuit !

    Franck Soriano a fait un Comparatif des architectures des API d'accès aux données, j'en rêvais depuis des années d'avoir un article de ce genre . Tout y ai clairement expliqué.

    S'il y a un point sur lequel je suis 100% d'accord avec ton chef, c'est bien de ne pas utiliser le Dataset .

    Comment être plus clair, j'ai épuisé toute les cartouches

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    excusez moi d'insister mais voila je veux vraiement essayer pour m'y faire à l'idée.



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ClassPrefixe.Close;
                  ClassPrefixe.CommandText:='Select distinct id_grille from where '+'id_grille='+''''+IntToStr(TgidInterne)+''''
                                      +' and prefixe='+''''+PrefFileInprog+''''  ;
                  ClassPrefixe.Active := true;
                  ClassPrefixe.Open;
    Le progblème est que l'open ne semble pas prendre en compte les critère de la requete, j'ai fait quelque chose de pas bien, mais quoi ???

    Merci

  4. #4
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Je t'ai donné un lien, arrête toi à l'architecture DBExpress et lis bien se paragraphe pour comprendre le mécanisme.

    Tu commets une erreur, tu créés juste un ClientDataset dynamiquement que tu utilises pour le cache. Où sont les autres maillons de la chaîne de ton architecture Datasnap, puisque c'est bien ça que tu utilises d'un point de vue fonctionnel, mais d'un point de vue performance l'article de Franck Soriano t'explique les avantages et les inconvénients de cette architecture ainsi que d'autres architectures.

    La propriété CommandText du clientdataset suppose que tu fonctionnes en architectures N Tiers (ie Datasnap) même si tu peux tout faire tourner dans une application cliente, mais c'est pas le but premier.

    Tu utilises ClientDataset parce qu'il est capable de stocker les informations en mémoire vive, mais son but n'est pas de stocker des millions d'enregistrements en cache, c'est le rôle d'une BDD.

    Je n'ai fais que résumer des points de l'article, alors je t'invites à le lire.

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    Merci

  6. #6
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par chaplin Voir le message
    Franck Soriano a fait un Comparatif des architectures des API d'accès aux données, j'en rêvais depuis des années d'avoir un article de ce genre . Tout y ai clairement expliqué.
    Merci !

    Je rempli donc mon clientdataset avec ce fichier de 3millions de lignes ~3 minutes

    maintenant comment faire un select distinct
    Evidemment, je suis le premier à penser que le ClientDataSet ne sera pas la solution la plus performante.
    Cependant en effet, rien ne vaut un bon test pour s'en assurer et vérifier ses hypothèses.

    Donc je vais qu'en même répondre à la question technique : "comment faire un select distinct ?"

    En fait, tu ne peux pas. Le clientDataSet utilisé de cette façon n'est rien d'autre qu'un DataSet en mémoire qu'on ne peut pas interroger avec une requête SQL.
    Cependant, on peut coder à la main le traitement qu'effectuerait un SGBD s'il devait faire le distinct :
    1. Il faut trier les données dans l'ordre du distinct :
    - Si tu veux faire un distinct Occurence1, Occurence2, tu commences par trier le dataset selon la clé <Occurence1, Occurence2> (pour celà, il suffit de définir un Index sur le dataset).
    2. Tu scannes le clientdataset, du début à la fin et tu regardes les lignes où les valeurs de Occurence1, Occurence2 changent par rapport à la ligne précédente. Comme le dataset est trié, chaque changement de valeur correspond à une nouvelle valeur unique.

    Si tu travailles de cette façon chaque tri s'effectuera en O(n*ln(n)). Ensuite tu ajoutes le scan en O(n). Au final le select distinct se comportera en O(n*ln(n)).

    Attention quand même :
    Travailler de cette façon nécessite de charger la totalité du fichier en mémoire. Si tu utilises un clientDataset avec 9 champs de 30 caractères, chaque ligne occupera au minimum 9*30 = 270 octets. Multiplier par 3M ça fait au minimum 810 Mo, pour charger un fichier qui faisait 300Mo au départ...

    Il va falloir que le la machine possède un maximum de mémoire vive...

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Août 2004
    Messages
    696
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 696
    Points : 225
    Points
    225
    Par défaut
    vous avez fini par me convaincre de laissé les datasets

    merci

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

Discussions similaires

  1. [AC-2002] Select distinct dans Requete analyse croisées
    Par Lidouminou dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 30/05/2012, 14h34
  2. SELECT DISTINCT dans une dataTable
    Par GreatDeveloperOnizuka dans le forum C#
    Réponses: 2
    Dernier message: 05/02/2010, 16h21
  3. Réponses: 1
    Dernier message: 12/06/2007, 21h38
  4. Garder l'ordre des Records dans une requete select distinct
    Par pobrouwers dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 21/02/2007, 22h06
  5. Selection distincte dans un dlookupcombobox
    Par Tyler Durden dans le forum Bases de données
    Réponses: 3
    Dernier message: 06/10/2005, 08h19

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