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 :

Aide analyse compréhention rédaction requête SQL


Sujet :

SQL Oracle

  1. #1
    Futur Membre du Club
    Aide analyse compréhention rédaction requête SQL
    Bonjour,

    Je cherche de l'aide pour comprendre une requête SQL Oracle.

    Mon objectif principal est d'avoir la somme par utilisateur (user_id) du nombre qui se trouve dans la colonne "nbr_units" avec les 2 leviers, valeur TRAN_TYPE 100 et 600.
    La requête que je joins sort des valeurs trop élevées en comparaison de la réalité, du coup je dois comprendre et voir ou cela déconne.
    Pouvez-vous m'aider à résoudre ce problème

    TRAN_TYPE = VARCHAR2 (3 CHAR)
    TRAN_NBR = NUMBER (9, 0)
    NBR_UNITS = NUMBER (13, 5)

    S'ajoute à ce problème que je n'obtiens pas de résulta quand dans mon SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 AND TRAN_TYPE = 600. Mais je le fais séparément j'obtiens des données ! Il doit y avoir une subtilité que je ne connais pas.

    Première question : Je comprend pas pourquoi l'utilisation d'un "LEFT JOIN". Si je suis bien renseigné, cela permet de retourner le nombre de caractère.
    Deuxième question : Le SUM(CASE WHENE ...) il compare la valeur qui est un ID unique. Comment il obtient la somme de "NBR_UNITS" par TRAN_TYPE pour l'utilisateur XX

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    select  ptt.user_id as "OPERATEUR", '1 - Pièces Recues' as "ETAPE",
    sum(case when ptt2.tran_nbr is not null then ptt2.nbr_units else ptt.nbr_units end) as "Nbr" 
    from prod_trkg_tran ptt
    left join (select * from prod_trkg_tran ptt2 where tran_type =600 and  trunc(create_date_time) = trunc(sysdate)) ptt2 on ptt2.cntr_nbr = ptt.cntr_nbr and rownum = 1
    where ptt.tran_type =100 and  trunc(ptt.create_date_time) = trunc(sysdate)
    group by ptt.user_id

  2. #2
    Modérateur

    Citation Envoyé par matmat94 Voir le message
    S'ajoute à ce problème que je n'obtiens pas de résulta quand dans mon SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 AND TRAN_TYPE = 600. Mais je le fais séparément j'obtiens des données ! Il doit y avoir une subtilité que je ne connais pas.
    Quand tu exécutes la requête SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 AND TRAN_TYPE = 600 tu recherches les lignes qui ont simultanément la valeur 100 et la valeur 600 dans leur colonne TRAN_TYPE, ce qui n'est pas possible.
    Il faut rechercher les lignes qui possèdent l'une de ces deux valeurs donc : SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 OR TRAN_TYPE = 600 ou mieux encore SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE IN (100, 600)
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  3. #3
    Modérateur

    Essayez ceci :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
      select user_id
           , coalesce( sum(case tran_type when 100 then nbr_units end)
                     , sum(case tran_type when 600 then nbr_units end)
                     ) as nbr_units
        from prod_trkg_tran
       where create_date_time >= trunc(sysdate)
         and create_date_time <  trunc(sysdate) + 1
         and tran_type        in (100, 600)
    group by user_id;

  4. #4
    Futur Membre du Club
    Citation Envoyé par al1_24 Voir le message
    Quand tu exécutes la requête SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 AND TRAN_TYPE = 600 tu recherches les lignes qui ont simultanément la valeur 100 et la valeur 600 dans leur colonne TRAN_TYPE, ce qui n'est pas possible.
    Il faut rechercher les lignes qui possèdent l'une de ces deux valeurs donc : SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE = 100 OR TRAN_TYPE = 600 ou mieux encore SELECT * FROM PROD_TRKG_TRAN WHERE TRAN_TYPE IN (100, 600)
    Bonjour Al1,

    MErci pour ta réponse, je comprend mieux pourquoi je n'avais pas de donné en retour.
    Grace à ton aide j'ai pu, enfin je pense avoir un résultat différent que de celui de la requête initial.
    Mais je ne sais pas si elle est en phase avec la réalité.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT user_id, count (nbr_units) 
    FROM PROD_TRKG_TRAN 
    WHERE TRAN_TYPE IN (100, 600) and  trunc(create_date_time) = trunc(sysdate)
    group by user_id

  5. #5
    Futur Membre du Club
    Citation Envoyé par Waldar Voir le message

    Bonjour Waldar,

    Merci pour ta réponse,
    J'ai essayé ta requête et j'obtiens un message d'erreur.

    ORA-00932: types de données incohérents ; attendu : CHAR ; obtenu : NUMBER
    00932. 00000 - "inconsistent datatypes: expected %s got %s"
    Quel est la fonction coalesce ?

    Encore merci pour ton aide.

  6. #6
    Rédacteur

    SQL est un langage typé avec transtypage automatique.

    Vous avez une colonne tran_type en VARCHAR (donc des littéraux) et vous voulez en comparer la valeur avec 100 qui est un nombre.
    Le moteur SQL obéit à votre demande et doit donc transtyper toutes les valeurs contenues dans la colonne tran_type en nombre pour effectuer cette comparaison. D'où votre message d'erreur s'il tombe sur un littéral qui n'est pas transtypable.

    Si vous aviez écrit votre requête comme suit :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    select user_id
           , coalesce( sum(case tran_type when '100' then nbr_units end)
                     , sum(case tran_type when '600' then nbr_units end)
                     ) as nbr_units
        from prod_trkg_tran
       where create_date_time >= trunc(sysdate)
         and create_date_time <  trunc(sysdate) + 1
         and tran_type        in ('100', '600')
    group by user_id;



    Vous n'auriez pas eu cette erreur.

    Apprenez le SQL !
    Mes livres, comme mon site web peuvent vous y aider
    https://SQLpro.developpez.com

    A +
    Cette signature n'a pas pu être affichée car elle comporte des erreurs.

  7. #7
    Futur Membre du Club
    Bonjour à tous,

    Merci pour votre car cela m'a bien aidé et permis d'aller au but.

    Pour info, SQLpro ta correction fonctionne parfaitement.
    Cependant, je comprend que SQL est autonome sur le transtypage, c'est bien ça ?

    Je n'est pas trouvé de documentation sur la fonction COALESCE, si vous avez un lien à me donner ca serait super cool.

    Comme WALDAR et SQLpro m'ont fournit une réponse correspondant à ce que je souhaite je vais me permettre de mettre en résolut la discutions.

    Je remercie encore les personnes ayant participé à la conversation et à la communauté pour votre aide.

    Matthieu

  8. #8
    Membre éclairé
    Citation Envoyé par matmat94 Voir le message

    Je n'est pas trouvé de documentation sur la fonction COALESCE, si vous avez un lien à me donner ca serait super cool.
    Matthieu
    Bonjour,

    Pourtant la documentation Oracle a cet avantage d'être assez exhaustive (même parfois pléthorique). En général je fais dans google "fonctionnalité recherchée + oracle + version" et je tombe quasiment tout le temps sur la doc officielle Oracle. Donc pour COALESCE, disons version 12.2, je tape ça dans google:

    coalesce oracle 12.2

    2è lien, directement sur la doc officielle et sur la fonction COALESCE:
    https://docs.oracle.com/en/database/...A-1DBF2CDE0C87

  9. #9
    Expert éminent
    COALESCE, c'est comme un multi NVL, ce qui n'est pas utile dans le cas d'un test sur 2 valeurs uniquement

    Attention, la requête de SQLPro te donne le nb de "tran_type=100", et s'il n'y en a pas le nb de "tran_type=600"
    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
    SELECT  NVL( SUM(CASE tran_type WHEN '100' THEN nbr_units END)
                 , SUM(CASE tran_type WHEN '600' THEN nbr_units END)
                 ) AS nbr_units
    FROM (		SELECT '100' tran_type, 1 nbr_units FROM dual
     		 UNION SELECT '600', 2 FROM dual)
    WHERE tran_type        IN ('100', '600')
    => 1
     
    SELECT  NVL( SUM(CASE tran_type WHEN '100' THEN nbr_units END)
                 , SUM(CASE tran_type WHEN '600' THEN nbr_units END)
                 ) AS nbr_units
    FROM (		SELECT '111' tran_type, 1 nbr_units FROM dual
        UNION SELECT '600', 2 FROM dual)
    WHERE tran_type        IN ('100', '600')
    => 2
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  10. #10
    Modérateur

    Citation Envoyé par McM Voir le message
    COALESCE, c'est comme un multi NVL, ce qui n'est pas utile dans le cas d'un test sur 2 valeurs uniquement
    Fonctionnellement oui, mais COALESCE est un NVL optimisé, il n'évalue pas les arguments qui suivent le premier non nul, contrairement à NVL qui évalue toujours ses deux arguments.

    C'est de l'optimisation probablement peu significative mais je ne vois pas pourquoi s'en passer.

###raw>template_hook.ano_emploi###