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

InterBase Discussion :

Sous-requête retournant une table


Sujet :

InterBase

  1. #1
    Membre à l'essai
    Homme Profil pro
    Retraité
    Inscrit en
    Janvier 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2006
    Messages : 20
    Points : 11
    Points
    11
    Par défaut Sous-requête retournant une table
    Bonjour,
    Je voudrais exécuter une requête de ce type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    select champ1, 
    from ( select champ1, champ2 from table1 order by champ2) T2
    group by champ1
    Le debugger donne une erreur "token unknow" sur le 2ième select.
    Est-ce qu'interbase n'accepte pas les sous-requêtes retournant une table?
    Si oui, comment peut-on s'en sortir facilement?

    J'utilise DelphiXE entreprise et INTERBASE fourni avec (interbase 2009).

    Merci d'avance pour votre aide.

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Déjà , dans ce SQL il y a une virgule en trop

    sous Firebird j'aurais fait une CTE (je suis fan , de plus c'est plus facile a lire)

    interbase accepte t'il cette syntaxe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    WITH T2 AS (SELECT champ1, champ2 FROM table1)
    SELECT champ1,Sum(champ2) from t2 group by champ1
    ce qui permet des choses comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    WITH T1 AS (SELECT champ1, champ2 FROM table1),
                         T2 AS (SELECT Champ1,Sum(Champ3) as St3 From table2 
                                    Group by champ1)
    SELECT champ1,Sum(champ2),max(st3)  from t1 join t2 on t1.champ1=t2.champ1
    group by champ1
    mais tout cela est trop vague
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre à l'essai
    Homme Profil pro
    Retraité
    Inscrit en
    Janvier 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2006
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    La syntaxe With n'est pas acceptée par interbase.
    Est-ce qu'une solution comme indiquée ci-dessous serait envisageable?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    CREATE TABLE T2 AS 
    SELECT champ1, champ2 FROM table1 WHERE champ2='Une valeur' 
    //EXEC SQL
     
    SELECT champ1 FROM T2 
    GROUP BY champ1
     
    //Utilisation du résultat du select ->Rempli les Items d''une ComboBox à l''aide du champ1
     
    CLOSE T2
    //EXEC SQL
     
    DROP T2
    //EXEC SQL
    Si cette solution fonctionne, créer une table pour un tri intermédiaire me parait très lourd.
    N'y a t-il vraiment pas de solution simple pour ce problème, avec INTERBASE ?

  4. #4
    Membre à l'essai
    Homme Profil pro
    Retraité
    Inscrit en
    Janvier 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2006
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Bon,.. comme à priori, INTERBASE ne semble pas très bon sur ce coup là, je me suis rabattu sur la programmation pascal habituelle pour résoudre mon problème.
    Ce que j'avais besoin, c'est une liste d'items d'un champ, en assurant qu'il n'y ait aucune redondance.
    J'ai codé ça
    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
    vSQL:='SELECT champ1, champ2 from table1 WHERE Champ2 = "UneCertaineValeur"';
    iniComboBoxNonRedondance(Combo_NomCommercial,IBQuery_JeuxPourNomCommercial,vSQL,'champ1');
    {------------------------------------------------------------------------------}
    procedure TfrmEcranPourOperateur.iniComboBoxNonRedondance(Cbx: TComboBox; Dset :TDataset; const vSQL, Champ1:string);
    {Initialise une ComboBox en interdisant toute redondance.                      }
    var
     I : integer;
     ChampItems : TStringList;
    begin
     ChampItems:=TStringList.Create;
     Cbx.Clear;
     if IBDatabaseSuiviAff_Mach.Connected then begin
         if Dset is TIBQuery then
             IBQuery_SelectCloseOpen(Dset,vSQL);
         ChampItems.Clear;
         ChampItems.Sorted:=true;
         ChampItems.Duplicates:=dupIgnore;
         while not Dset.Eof do begin
             if Dset.FieldByName(Champ1).AsString<>'' then begin
                 ChampItems.Add(Dset.FieldByName(Champ1).AsString);
                 end;
             Dset.Next;
         end;
         Dset.First;
         for I := 0 to ChampItems.Count-1 do
             Cbx.Items.Add(ChampItems.Strings[I]);
         end;
     Cbx.Sorted:=true;
     Cbx.ItemIndex:=0;
     Cbx.Text:=Cbx.Items[Cbx.ItemIndex];
     ChampItems.Destroy;
    end;
    et ça fonctionne!
    En fait, toute l'astuce est dans le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ChampItems.Duplicates:=dupIgnore;

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Et avec des Vues (VIEW) ?

    Sur mes vieux souvenirs , une vue ne stocke (duplique) pas les données mais seulement le SQL
    ensuite il suffit d'utiliser la vue comme une table

    euh , pas besoin du duplicates:=dupIgnore un DISTINCT fait l'affaire

    vSQL:='SELECT DISTINCT champ1, champ2 from table1 WHERE Champ2 = "UneCertaineValeur"';
    ou un GROUP BY

    vSQL:='SELECT champ1, Max(champ2) from table1 WHERE Champ2 = "UneCertaineValeur"';
    GROUP BY 1
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  6. #6
    Membre à l'essai
    Homme Profil pro
    Retraité
    Inscrit en
    Janvier 2006
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 71
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2006
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    J'ai essayé avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    vSQL:='SELECT champ1, Max(champ2) from table1 WHERE Champ2 = "UneCertaineValeur"';
    GROUP BY champ1
    et ça fonctionne bien. J'obtiens moins d'Items qu'avec ma programmation, mais j'ai vérifié, il y a des valeurs de Champ2 qui sont quelque fois égales à null, donc ça doit être normal.
    L'astuce ici est donc d'inclure un champ dans un GROUP BY en utilisant un Max( ) afin de pouvoir utiliser cette variable dans le WHERE. Je ne savais pas que l'on pouvait faire cela!
    Cette solution est intéressante car très simple. Le tout est de savoir jongler avec les requêtes SQL...
    Au sujet de pouvoir résoudre le problème (ce n'est plus vraiment d'actualité du fait que la méthode donnée ci-dessus est pleinement satisfaisante, mais j'aime bien savoir...) avec une Table ou View intermédiaire:
    - View->J'ai envisagé la chose, mais comme j'étais obligé de résoudre le Pb en 2 temps
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE VIEW T2 AS 
    SELECT champ1, champ2 FROM table1 WHERE champ2='Une valeur' 
    //EXEC SQL
     
    SELECT champ1 FROM T2 
    GROUP BY champ1
    J'ai lu qu'il n'était pas possible de faire un SELECT sur un View. Une fois créé, on peut lire ce qu'il y a dedans, mais on ne peut plus travailler sur ses données... donc j'ai obté pour la table.
    - Dans mes essais avec la VIEW et la TABLE, à la création, pas de problème, mais au moment du DROP, j'ai obtenu une erreur du type
    la Table/View est utilisée, il n'est pas possible de l'enlever
    Je n'ai pas su aller plus loin.
    - Un dernier point au sujet du travail sur une table intermédiaire. Si un premier utilisateur par l'application créé la table
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE TABLE T2 AS 
    SELECT champ1, champ2 FROM table1 WHERE champ2='Une valeur'
    ->COMMIT. Un autre presque au même moment fait la même chose->Il y a une 2ième création de table! L'appli du 1ier fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT champ1 FROM T2 
    GROUP BY champ1
    , puis COMMIT, Etc... c'est la sac de noeuds complet!
    Qu'est-ce qui se passe en réalité. Mon hypothèse de travail est peut être complètement farfelue. Merci de m'éclairer à ce sujet.

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 021
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 021
    Points : 40 935
    Points
    40 935
    Billets dans le blog
    62
    Par défaut
    Citation Envoyé par billbocquet Voir le message
    J'ai essayé avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    vSQL:='SELECT champ1, Max(champ2) from table1 WHERE Champ2 = "UneCertaineValeur"';
    GROUP BY champ1
    et ça fonctionne bien. J'obtiens moins d'Items qu'avec ma programmation, mais j'ai vérifié, il y a des valeurs de Champ2 qui sont quelque fois égales à null, donc ça doit être normal.
    ça c'est qu'une question de Where à manier , le distinct doit fonctionner aussi
    J'ai lu qu'il n'était pas possible de faire un SELECT sur un View. Une fois créé, on peut lire ce qu'il y a dedans, mais on ne peut plus travailler sur ses données...
    Première nouvelle
    Mon hypothèse de travail est peut être complètement farfelue. Merci de m'éclairer à ce sujet.
    OUI , c'est farfelu j'y mets une ampoule 100W

    le problème c'est que tu semble absolument vouloir passer par des tables intermédiaires a créer et détruire (des GLOBAL TEMPORARY TABLE dans le jargon, ça existe , la preuve) mais tu demandes de l'aide en mettant demandant des ordres tellement généraux qu'il est très difficile de répondre :

    un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select champ1,champ2 from table1 where champ2="une valeur"
    franchement c'est pas terrible , dans ton cas on ne sait pas
    - Quelle est la structure de la table, s'il y a des index , le type de champ et s'il est 'nullifiable' !
    - aucun jeu d'essai
    - aucun élément sur le résultat a trouver

    une demande très vague (on n'est pas dans ta tête) ne pourra que donner une réponse vague (le fameux 'GIGO')
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

Discussions similaires

  1. [10g] Requête retournant une liste de tables contenant un même champs
    Par appaloosa753 dans le forum PL/SQL
    Réponses: 2
    Dernier message: 04/03/2014, 16h23
  2. Sous requête retournant une table
    Par tleboukaka dans le forum Bases de données
    Réponses: 1
    Dernier message: 01/10/2007, 15h16
  3. Réponses: 2
    Dernier message: 02/06/2006, 12h26
  4. impression sous builder (d'une table mysql)
    Par Link45 dans le forum C++Builder
    Réponses: 15
    Dernier message: 13/03/2006, 22h31
  5. Comment retourner une table !
    Par ptidoudou02 dans le forum Langage SQL
    Réponses: 7
    Dernier message: 14/12/2004, 15h46

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