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

DB2 Discussion :

[Pagination] Récupération limitée d'un résultat de requête


Sujet :

DB2

  1. #1
    hdd
    hdd est déconnecté
    Membre régulier Avatar de hdd
    Profil pro
    Inscrit en
    février 2004
    Messages
    105
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : février 2004
    Messages : 105
    Points : 74
    Points
    74
    Par défaut [Pagination] Récupération limitée d'un résultat de requête
    Bonjour,

    Est-il possible avec DB2 de limiter le nombre de résultats d'une requête, mais à partir d'un offset donné ? Par exemple, je voudrais, pour une requête retournant une centaine de lignes, les lignes 30 à 75.

  2. #2
    jab
    jab est déconnecté
    Rédacteur
    Avatar de jab
    Homme Profil pro
    SharePoint developpeur
    Inscrit en
    février 2004
    Messages
    1 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : SharePoint developpeur
    Secteur : Service public

    Informations forums :
    Inscription : février 2004
    Messages : 1 173
    Points : 4 339
    Points
    4 339
    Par défaut
    Il n'y a pas comme en MySql un système de pagination mais tu peux résoudre le problème ainsi.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    WITH TEMPTABLE AS 
    (SELECT *, ROW_NUMBER() OVER (ORDER BY monChampTri DESC) AS NUMREC 
    FROM maTable) 
    SELECT * 
    FROM TEMPTABLE
    WHERE NUMREC BETWEEN 30 AND 75
    J'espère que cela résoud ton problème.

  3. #3
    Membre habitué
    Inscrit en
    juin 2004
    Messages
    213
    Détails du profil
    Informations forums :
    Inscription : juin 2004
    Messages : 213
    Points : 154
    Points
    154
    Par défaut
    Jab y'a pas plus imple que ça pour limiter le nombre de lignes retournées par un select?

    Car j'ai une requête qui doit me ramener tellement de lignes que l'as400 monte a 90% d'utilisation donc tout le monde gueule à mon taf

    J'ai essayer avec la clause mais ça ne sert pas à grand chose dans mon cas donc si il y avait une solution assez simple ce serait cool

    merci d'avance

  4. #4
    jab
    jab est déconnecté
    Rédacteur
    Avatar de jab
    Homme Profil pro
    SharePoint developpeur
    Inscrit en
    février 2004
    Messages
    1 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : SharePoint developpeur
    Secteur : Service public

    Informations forums :
    Inscription : février 2004
    Messages : 1 173
    Points : 4 339
    Points
    4 339
    Par défaut
    En effet optimize ne sert pas à limiter le résultat. Il y a bien la clause

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    FETCH FIRST n ROW ou ROWS (je ne sais plus)
    mais comme cela l'indique, c'est les x premières lignes.

    Avec tu peux optimizer le premier SELECT mais in fine tu devras quand même tout lire.

    Une option serait de créer une table temporaire avec le premier SELECT ce qui évite de le regénérer à chaque fois. Tu mets NumRec dans la clé primaire pour optimizer la seconde requête. Tu peux éventuellement ne mettre dans cette table temporaire que numrec et la clé primaire de ta table et travailler avec une jointure. La création de la table devrait être plus rapide.

    Sinon je ne vois pas mais peut être que d'autres ?

    J'essaye de me renseigner.

  5. #5
    Membre expert
    Homme Profil pro
    Retraité
    Inscrit en
    octobre 2005
    Messages
    1 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Finance

    Informations forums :
    Inscription : octobre 2005
    Messages : 1 454
    Points : 3 195
    Points
    3 195
    Par défaut
    Et l'idée toute simple de réécrire la requête de façon à ne ramener qu'un nombre limité et raisonnable de lignes ?

  6. #6
    Membre habitué
    Inscrit en
    juin 2004
    Messages
    213
    Détails du profil
    Informations forums :
    Inscription : juin 2004
    Messages : 213
    Points : 154
    Points
    154
    Par défaut
    Merci jab pour ta réponse mais le problème c'est que je ne veux pas que le select cherche tout les enregistrements!!

    Merci Luc pour ta réponse qui va je pense faire avancer les choses , si ma requête mets aussi longtemps à s'éxécuter c'est qu'elle fait une liaison entre 3tables qui sont également liées sur elle-même donc je ne peut pas faire plus simple sinon je n'aurais pas le résultat que je veux. Je précise que mes tables comportent chacune environ 41000 enregistrements distinct donc je pense que le faire que la requête soit aussi longue vient de là

  7. #7
    jab
    jab est déconnecté
    Rédacteur
    Avatar de jab
    Homme Profil pro
    SharePoint developpeur
    Inscrit en
    février 2004
    Messages
    1 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : SharePoint developpeur
    Secteur : Service public

    Informations forums :
    Inscription : février 2004
    Messages : 1 173
    Points : 4 339
    Points
    4 339
    Par défaut
    Peux-tu montrer la commande que tu utilise actuellement, il sera plus facile de se rendre compte de quoi faire.

  8. #8
    Membre habitué
    Inscrit en
    juin 2004
    Messages
    213
    Détails du profil
    Informations forums :
    Inscription : juin 2004
    Messages : 213
    Points : 154
    Points
    154
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT m9cono, m9itno 
    FROM mitfac 
    WHERE m9cono not in (SELECT PHPRNO 
         FROM mpdhed, mitmas 
         WHERE MPDHED.PHCONO=m9cono 
         AND MITMAS.MMITNO=m9itno     
         AND (MITMAS.MMMABU=2 
         AND (phcono NOT LIKE '7%' 
         OR phcono like8%’)))
    			AND m9cono=100

  9. #9
    Nouveau membre du Club
    Inscrit en
    décembre 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : décembre 2005
    Messages : 25
    Points : 30
    Points
    30
    Par défaut
    Citation Envoyé par jab
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    FETCH FIRST n ROW ou ROWS (je ne sais plus)
    Les 2 mon capitaine. Mais il me semble qu'il faut ajouter ONLY à la fin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FETCH FIRST n ROW(S) ONLY
    Yoyopi, si ta requête est longue c'est peut-être aussi parce qu'il y a création d'index temporaires.

  10. #10
    Membre habitué
    Inscrit en
    juin 2004
    Messages
    213
    Détails du profil
    Informations forums :
    Inscription : juin 2004
    Messages : 213
    Points : 154
    Points
    154
    Par défaut
    Salut gwellan tu vas bien depuis le temps?!!!

    Oui ma requête créer des index, c'est pas possible d'éviter leur création?

    Le FETCH ca va pas m'aider car je veux que mon select lorqu'il a trouver x enregistrements il s'arrète mais ça a pas l'air possible

  11. #11
    Nouveau membre du Club
    Inscrit en
    décembre 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : décembre 2005
    Messages : 25
    Points : 30
    Points
    30
    Par défaut
    Ca va, merci
    Si tu as un index sur : Si dans ta requête tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where col2=x and col1=y and col3=z
    Il risque de ne pas prendre ton index. IBM recommande de mettre tes conditions dans le même ordre que pour l'index :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where col1=y and col2=x and col3=z
    Et si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where col2=x and col3=y
    C'est perdu d'avance...
    Par contre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    where col1=x and col2=y
    fonctionnera parfaitement.
    Après sur les requêtes complexes il lui arrive quand même de se perdre. Ca m'est arrivé plus d'une fois où l'optimiseur m'a dit "ce serait bien de créer un index sur les colonnes x, y", tu crées l'index en question et il te redit quand même que "ce serait bien de créer un index sur x, y".

    Note :
    Je parle là de DB2/400, utilisé par Yoyopi. Je ne sais pas si ce fonctionnement est indentique sur les autres plateformes DB2.

  12. #12
    Membre éprouvé

    Homme Profil pro
    Consultant informatique
    Inscrit en
    mars 2002
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : mars 2002
    Messages : 72
    Points : 1 042
    Points
    1 042
    Par défaut
    Sur Iseries V5r3 sous Db2400 ,

    Il est possible d'utiliser un curseur dit scrollable qui permet de se position a l'enregistrement de son choix avec l'instruction FETCH relative et aussi de lire le nombre d'enregistrement de son choix.

    Voici un exemple tiré du redbook d'IBM sur les procédures stockées :
    Stored Procedures
    and Triggers
    on DB2 Universal Database for iSeries



    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
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
     
    CREATE PROCEDURE GETRANK 1
    (IN proc_year DECIMAL(4,0),1
    IN proc_month DECIMAL(2,0),1
    INOUT proc_rank INTEGER)1
    RESULT SETS 2 2
    LANGUAGE SQL 3
     
    BEGIN
     
    DECLARE highsales DECIMAL(11,2);
    DECLARE lowsales DECIMAL(11,2);
    DECLARE rank1 INTEGER;
    DECLARE rank2 INTEGER;
    DECLARE SQLStmt CHAR(512);
    DECLARE c1 DYNAMIC SCROLL CURSOR WITH RETURN FOR s1;4
    DECLARE c2 DYNAMIC SCROLL CURSOR WITH RETURN FOR s2;4
     
    ---Check if it is Null for Month
    IF proc_month IS NULL or proc_month =0 THEN
    --Get Highest Rank Suppliers
    SET SQLStmt='SELECT yearsales FROM yearsale WHERE year=?
    ORDER BY yearsales DESC';5
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year;
     
    FETCH RELATIVE proc_rank FROM c1 INTO highsales;
     
    IF highsales IS NULL THEN
    FETCH LAST FROM c1 INTO highsales;
    END IF;
     
    CLOSE c1;
     
    SET SQLStmt='SELECT count(*)FROM yearsale WHERE year=?AND yearsales>=?';
     
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year,highsales;
     
    FETCH c1 INTO rank1;
    CLOSE c1;
    SET SQLStmt='SELECT supplier_name,yearsales FROM yearsale WHERE year=?
    AND yearsales>=?ORDER BY yearsales DESC';5
     
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year,highsales;
    --Get Lowest Rank Suppliers
    SET SQLStmt='SELECT yearsales FROM yearsale WHERE year=?
    ORDER by yearsales ASC';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year;
    FETCH RELATIVE proc_rank FROM c2 INTO lowsales;6
    IF lowsales IS NULL THEN 7
    FETCH LAST FROM c2 INTO lowsales;
    END IF;
    CLOSE c2;
     
    SET SQLStmt='SELECT count(*)FROM yearsale WHERE year=?AND yearsales<=?';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year,lowsales;
    FETCH c2 INTO rank2;
    CLOSE c2;
     
    SET SQLStmt='SELECT supplier_name,yearsales FROM yearsale WHERE year=?
    AND yearsales<=?ORDER BY yearsales ASC';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year,lowsales;
     
    ELSE
     
    --Get Highest Rank Suppliers
    SET SQLStmt='SELECT totalsales FROM TOTALSALE WHERE year=?
    AND month=?ORDER BY totalsales DESC';
     
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year,proc_month;
     
    FETCH RELATIVE proc_rank FROM c1 INTO highsales;
    IF highsales IS NULL THEN
    FETCH LAST FROM c1 INTO highsales;
    END IF;
     
    CLOSE c1;
     
    SET SQLStmt='SELECT count(*)FROM totalsale WHERE year=?AND month=?
    AND totalsales>=?';
     
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year,proc_month,highsales;
     
    FETCH c1 INTO rank1;
    CLOSE c1;
     
    SET SQLStmt='SELECT supplier_name,totalsales FROM totalsale WHERE year=?
    AND month=?AND totalsales>=?
    ORDER BY totalsales DESC';
     
    PREPARE s1 FROM SQLStmt;
     
    OPEN c1 USING proc_year,proc_month,highsales;
    --Get Lowest Rank Suppliers
    SET SQLStmt='SELECT totalsales FROM totalsale WHERE year=?AND month=?
    ORDER by totalsales ASC';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year,proc_month;
     
    FETCH RELATIVE proc_rank FROM c2 INTO lowsales;
    IF lowsales IS NULL THEN
    FETCH LAST FROM c2 INTO lowsales;
    END IF;
     
    CLOSE c2;
    SET SQLStmt='SELECT count(*)FROM totalsale WHERE year=?AND month=?
    AND totalsales<=?';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year,proc_month,lowsales;
     
    FETCH c2 INTO rank2;
    CLOSE c2;
     
    SET SQLStmt='SELECT supplier_name,totalsales FROM totalsale WHERE year=?
    AND month=?AND totalsales<=?
    ORDER BY totalsales ASC';
     
    PREPARE s2 FROM SQLStmt;
     
    OPEN c2 USING proc_year,proc_month,lowsales;
    END IF;
    IF rank1<rank2 THEN
    SET proc_rank=rank2;
    ELSE
    SET proc_rank=rank1;
    END IF;
    END
    Ancien rédacteur Java/J2EE ,C++Builder

Discussions similaires

  1. [Requêtes] Limiter nombre de résultats
    Par windmastr26 dans le forum HyperFileSQL
    Réponses: 5
    Dernier message: 19/02/2011, 15h33
  2. Limiter des résultats de requête contenant un GROUP BY
    Par jcachico dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 19/10/2008, 17h03
  3. [MySQL] Pagination d'un résultat de requête
    Par MaxAurele dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 18/06/2008, 21h41
  4. Pagination d'un résultat de requête
    Par Methode dans le forum Langage
    Réponses: 1
    Dernier message: 03/01/2007, 16h47

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