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

SQL Oracle Discussion :

Génération de n lignes à partir d'une seule - intervalle


Sujet :

SQL Oracle

  1. #1
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut Génération de n lignes à partir d'une seule - intervalle
    Bonjour,

    J'ai en source une table qui contient des intervalles numériques ( paliers ).
    A partir de cette table je dois générer toutes les lignes.

    Un exemple sera plus parlant :

    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
     
    with 
     t as (
      select 1 id, 2 val, 1 deb, 4 fin from dual union all
      select 1 id, 4 val, 5 deb, 6 fin from dual union all
      select 2 id, 3 val, 1 deb, 2 fin from dual ),
     n as (
      select 1 n from dual union all
      select 2 n from dual union all
      select 3 n from dual union all
      select 4 n from dual union all
      select 5 n from dual union all
      select 6 n from dual )
    select
      t.id, n.n, t.val
    from t, n
    where n.n between t.deb and t.fin
    order by 1,2
    A partir de 3 lignes j'en génère 6 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ID	N	VAL
    1	1	2
    1	2	2
    1	3	2
    1	4	2
    1	5	4
    1	6	4
    2	1	3
    2	2	3
    Ca marche bien, mais créer une table où on ne stockerait qu'une séquence ne me parait pas la solution la plus propre.
    Existe-t-il un autre moyen que de passer par une table "bidon" ?

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Vous pouvez utiliser, à vos risques et péril car non documenté, le connect by level pour générer une suite de nombre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        select level
          from dual
    CONNECT by level <= 6;
    Si vous voulez être plus précis vous pouvez calculer la plage exacte à couvrir :
    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
    WITH t1 AS
    (
    SELECT 1 as id, 2 as val, 1 as deb, 4 as fin FROM dual union ALL
    SELECT 1      , 4       , 5       , 6        FROM dual union ALL
    SELECT 2      , 3       , 1       , 2        FROM dual
    )
      ,  t2 as
    (
    select max(fin) - min(deb) + 1 as cpt_inter,
           min(deb) as cpt_min
      from t1
    )
      ,  t3 as
    (
        select level - 1 + cpt_min as cpt
          from t2
    CONNECT by level <= cpt_inter
    )
      select t1.id, t1.val, t3.cpt
        from t1
             inner join t3
               on t3.cpt between t1.deb and t1.fin
    order by t1.id asc, t1.val asc;
     
    ID   VAL  CPT
    1    2    1
    1    2    2
    1    2    3
    1    2    4
    1    4    5
    1    4    6
    2    3    1
    2    3    2

  3. #3
    Membre habitué
    Inscrit en
    Mai 2010
    Messages
    107
    Détails du profil
    Informations forums :
    Inscription : Mai 2010
    Messages : 107
    Points : 132
    Points
    132
    Par défaut
    La technique de Waldar est meilleure car utilise DUAL. La plupart des requêtes utilisant DUAL sont optimisées. Mais la technique peut ne pas (quoique) fonctionner dans les prochaines versions d'Oracle...

    Sinon, il y a le simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT ROWNUM FROM ALL_OBJECTS WHERE ROWNUM < 10;
    s'il n'y a pas énormément d'enregistrements à générer.

    Ou bien, il y a le GROUP BY CUBE
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT ROW_NUMBER() OVER(ORDER BY 1)  FROM DUAL GROUP BY CUBE(1,2,3,4,5);
    qui générera 2^5 enregistrements.

    Ce sont les 3 techniques que j'utilise moi pour générer des enregistrements.

  4. #4
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Une fonction pipelined peut remplacer assez efficacement le "connect by level"

  5. #5
    Expert confirmé
    Avatar de doc malkovich
    Homme Profil pro
    Consultant en Business Intelligence
    Inscrit en
    Juillet 2008
    Messages
    1 884
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Consultant en Business Intelligence

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 884
    Points : 4 285
    Points
    4 285
    Billets dans le blog
    1
    Par défaut
    Le connect by level marche bien

    Merci

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

Discussions similaires

  1. [11g] Charger plusieurs lignes à partir d'une seule
    Par raz2008 dans le forum SQL*Loader
    Réponses: 2
    Dernier message: 02/12/2013, 15h55
  2. Réponses: 3
    Dernier message: 24/10/2008, 19h31
  3. Réponses: 2
    Dernier message: 22/10/2008, 17h53
  4. [débutant] vue / creer 2 lignes a partir d'une seule
    Par Flamby38 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 28/05/2008, 12h26
  5. [CR] Génération d'un état à partir d'une page ASP
    Par marceline dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 01/08/2006, 12h28

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