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 :

Inverser le sens d'une requête SQL..


Sujet :

SQL Oracle

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut Inverser le sens d'une requête SQL..
    Bonjour

    Je possède une table T1 comme ceci :
    Nombre(Number(5))
    Chaîne(Varchar2(40))

    Le champ 'nombre' contient des valeurs numériques, de 0 à 86000 environ (il y en a environ 35000 différents en tout).

    J'ai actuellement une requête croisée, me retournant le total des champs possédant un nombre et une chaîne donnée, soit environ ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Chaîne    0    1  ...  20    30 ....  90000   100000  ...
     
    chaîne1  12    43    546     76      7878       785
    chaîne2   2    345   757     67       876        67
    chaîne3  437   3     43      76       879        908
    J'ai donc un regroupement par chaîne, et quelques enregistrements du champ "Nombre". En effet, je n'ai pas 1 colonne par valeur, mais un regroupement! Je m'explique :
    je compte de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT chaîne,
    count(CASE WHEN Nombre=0 THEN 1 END)AS M_0,
    count(CASE WHEN Nombre=1 THEN 1 END)AS M_1,
    ...
    count(CASE WHEN Nombre>=100 AND Nombre<200 THEN 1 END)AS M_100_200,
    ...
    count(CASE WHEN Nombre>=90000 AND Nombre<100000 THEN 1 END)AS M_90000_100000,
    ...
    FROM T1
    GROUP BY chaîne ORDER BY chaîne;
    Le soucis c'est que je souhaite obtenir l'inverse! Soit les chaînes en entête de colonne, et les valeurs de "Nombre" (regroupés comme je vous l'ai montré) en entête de ligne...
    Pour les chaînes en entête ce n'est pas un problème, j'ai le moyen de les récupérer toutes (donc je peux faire un "CASE(WHEN chaine="chaine1" THEN 1 END)" etc..), mais comment faire pour le regroupement du champ "nombre" ? (si je met "GROUP BY nombre", j'ai bien évidemment les 35000 lignes qui s'affichent...)!

    Une idée ?...

    Merci beaucoup

  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 386
    Points
    18 386
    Par défaut
    Il suffit de regrouper tous vos cases sur les nombres en un seul, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CASE
      WHEN Nombre = 0 THEN 0
      WHEN Nombre = 1 THEN 1
      ...
      WHEN Nombre BETWEEN 100 AND 200 THEN 100
      ...
      WHEN Nombre BETWEEN 90000 AND 100000 THEN 90000
      ...
    END
    Si vous avez une logique de regroupement, ce serait encore mieux il suffirait d'appliquer la fonction mathématique.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut
    c'était donc ça ? Je n'ai pas encore testé (j'ai surtout essayé de comprendre ^^)! D'ailleurs, si je comprend bien ça signifie qu'il n'y a plus de clause GROUP BY !? (de toute façon théoriquement ça doit planter si j'en met une), étant donné que tout est déjà regroupé dans un seul champ!
    C'est génial, je vais tester ça de suite

    ps : j'ai un algorithme qui me fait la petite règle de regroupement des nombres Effectivement ça serait beaucoup trop long sinon
    Merci encore !!

  4. #4
    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 386
    Points
    18 386
    Par défaut
    Le regroupement doit être et dans le select et dans le group by, bien entendu.
    Regardez je vous ai fait les deux pivots rapidement ici :
    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 MaTable as
    (
    select 'A' as c1, 12 as c2 from dual union all
    select 'B'      , 23       from dual union all
    select 'A'      ,  9       from dual union all
    select 'B'      , 31       from dual
    )
      select c1,
             count(case when c2 between  0 and  9 then 1 end) as c2_10,
             count(case when c2 between 10 and 19 then 1 end) as c2_20,
             count(case when c2 between 20 and 29 then 1 end) as c2_30
        from MaTable
    group by c1
    order by c1 asc;
     
    C1	C2_10	C2_20	C2_30
    A	1	1	0
    B	0	0	1
    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
    With MaTable as
    (
    select 'A' as c1, 12 as c2 from dual union all
    select 'B'      , 23       from dual union all
    select 'A'      ,  9       from dual union all
    select 'B'      , 31       from dual
    )
      select floor(c2/10) as c2_grp,
             count(case c1 when 'A' then 1 end) as c1_A,
             count(case c1 when 'B' then 1 end) as c1_B
        from MaTable
    group by floor(c2/10)
    order by floor(c2/10) asc;
     
     
    C2_GRP	C1_A	C1_B
    0	1	0
    1	1	0
    2	0	1
    3	0	1

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut
    Merci beaucoup, mais il y a une chose que je ne comprend pas...
    Tout à l'heure vous faisiez un CASE global contenant tous les when, et maintenant vous faites un floor(c2/10)

    Parce que j'avais fait ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    select CASE WHEN nombre=0 THEN 0 WHEN nombre=1 THEN 1 etc..,
    count(case chaine when 'chaine1' then 1 end) AS c1_A,
    count(case chaine when 'chaine2' then 1 end) AS c1_B
    FROM T1
    Mais à vrai dire je me retrouve avec une erreur "ora-00939", soit "too many arguments"... Donc il faut que je limite les champs dans MA requête

  6. #6
    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 386
    Points
    18 386
    Par défaut
    Le floor ici c'est la fameux algorithme de regroupement.
    J'aurai pu l'écrire ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CASE
      when c2 BETWEEN  0 AND  9 then 0
      when c2 BETWEEN 10 AND 19 then 1
      when c2 BETWEEN 20 AND 29 then 2
      else 3
    end
    D'où ma remarque, c'est plus rapide d'écrire une fonction quand il y a une logique de regroupement.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut
    Merci Waldar pour votre réponse
    Cependant, la logique que je souhaite obtenir est un peu différente..
    Dans ma colonne "Nombre", il y a environ 35000 valeurs (je rappelle que les valeurs montent plus ou moins jusqu'à 86000).

    Ce que je voudrais dans mon résultat, c'est afficher le nombre de valeurs de 1 à 150 par pas de 1, et les valeurs suivantes par pas de 100 (jusqu'à 90000 histoire d'être tranquille). En effet, les quelques premiers milliers de valeurs de la colonne "Nombre" se suivent (de 1 en 1 donc), ce n'est qu'à partir d'un certain nombre de valeurs que l'on a des "trous".
    On a donc quelque chose comme ceci :
    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
     
    C2
     
    1
    2
    3
    4
    ...
    149
    150
    250
    350
    450
    ...
    90000
    Mais comment obtenir ceci ? Floor(n) ne peut pas m'aider ici J'ai donc tout passé en un seul CASE, mais j'obtiens l'erreur du nombre d'arguments trop important..
    Merci beaucoup

  8. #8
    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 386
    Points
    18 386
    Par défaut
    Il faut combiner un peu tout !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    case
      when nombre <= 150 then nombre
      else floor((nombre - 150) / 100) * 100
    end

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Il faut combiner un peu tout !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    case
      when nombre <= 150 then nombre
      else floor((nombre - 150) / 100) * 100
    end
    Merci infiniment, j'ai compris l'astuce
    Cependant, il y a une erreur dans votre floor (je crois )
    En effet, imaginons que je prenne le nombre 321. Si je souhaite un pas de 100, celà signifie qu'il sera rangé dans le groupement des 300_400.

    Donc pourquoi faire floor(nombre -150) ? Le "-150" est inutile et fausse les résultats non?
    Car floor((321-150)/100)*100 = floor(171/100)*100 = 1*100 = 100 !?

    Sans le "-150" on obtient bien 300 (du moins c'est ce que moi je recherche, peut-être ne l'aviez vous pas compris comme ça)
    En tout cas merci beaucoup pour toutes vos explications, et pour cette fonction va m'être très utile pour la suite!

  10. #10
    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 386
    Points
    18 386
    Par défaut
    Effectivement j'ai oublié de remettre les 150 après :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    floor((nombre - 150) / 100) * 100 + 150
    Si je ne fais pas ce -150 / +150, tous les nombres entre 150 et 200 vont valoir 100, hors 100 est déjà pris dans vos pas unitaires.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Avril 2010
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 134
    Points : 71
    Points
    71
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Si je ne fais pas ce -150 / +150, tous les nombres entre 150 et 200 vont valoir 100, hors 100 est déjà pris dans vos pas unitaires.
    Tout à fait, d'ailleurs je n'avais même pas remarqué que le +150 remédiait au problème Moi et les maths...
    Merci encore

Discussions similaires

  1. Utilisation de MAX dans une requête SQL
    Par Evil onE dans le forum Langage SQL
    Réponses: 7
    Dernier message: 15/06/2004, 18h38
  2. Récupurer via une requête SQL la valeur la plus proche
    Par yoda_style dans le forum Langage SQL
    Réponses: 9
    Dernier message: 27/04/2004, 13h52
  3. Résultat d'une requète SQL
    Par camino dans le forum Bases de données
    Réponses: 2
    Dernier message: 21/02/2004, 15h22
  4. A propos d'une requête SQL sur plusieurs tables...
    Par ylebihan dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/09/2003, 16h26
  5. inverser la lecture d'une requète
    Par nilaco dans le forum Requêtes
    Réponses: 5
    Dernier message: 10/08/2003, 12h16

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