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

Langage SQL Discussion :

Proc SQL : valeur de la ligne en fonction des noms de colonnes non nulles


Sujet :

Langage SQL

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Proc SQL : valeur de la ligne en fonction des noms de colonnes non nulles
    Bonjour,

    Voici ce que je voudrais faire :
    Soit une table T, ayant 6 colonnes appelées C1, C2, ... C6.
    ==> SVP comment faire pour que dans ma colonne "Resultat", pour chaque ligne, apparaisse les noms des colonnes > 0 ?

    Autrement dit, par exemple :
    - Si à la ligne 1, C1 et C5 ne sont pas nulles, mais les autres oui, alors "Resultat" aura une valeur de type "C1, C5".
    - Si à la ligne 2, seule C3 n'est pas nulle, alors "C3".
    - Si à la ligne 3, seules C1, C4 et C6 sont positives, alors "C1, C4, C6".
    - etc.

    Merci pour votre aide !
    (j'ai voulu essayer avec " SELECT name FROM dictionary.columns WHERE libname = '....'
    AND memname = '....', mais pas sûr de cette piste.)

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 788
    Points
    30 788
    Par défaut
    Bonjour,

    Quelque chose comme ç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
    with    calcul
        as  (   select  C1, ..., C6
                    ,   case when c1 > 0 then 'C1,' else '' end
                    ||  ...
                    ||  case when c6 > 0 then 'C6,' else '' end as liste
                from    matable
            )
    select  C1, ..., C6
        ,   case when charlength(liste) > 0
                then substring(liste from 1 for charlength(liste) - 1)
                else ''
            end as resultat
    from    calcul
    ;
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Bonjour al1_24,

    Merci pour ton aide, mais j'ai une erreur avec le "with" (en fait je me sers de ce que tu fais pour remplir un "update set", donc je prends ce que tu fais, mais sans le "as Resultat" à la fin.)
    Voici l'erreur :

    ERROR 22-322: Erreur de syntaxe ; l'une des valeurs suivantes est attendue : ;, !!, (, *, **, +, ',', -, '.', /, WHERE, ||.


    Et j'ai essayé de le mettre sans l'update, en démarrant par "with", mais là il me met le "with" en rouge.

  4. #4
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 080
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 080
    Points : 30 788
    Points
    30 788
    Par défaut
    La requête que j'ai proposée correspondait au besoin exposé. Elle utilise la syntaxe normalisée du langage SQL.

    Sans connaitre le SGBD utilisé ni la requête exécutée, il est difficile d'analyser le message d'erreur pour proposer une correction...
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Alors merci beaucoup encore pour ta réponse initiale.
    En effet, je vais essayer d'apporter plus d'infos (n'étant pas expert je ferai de mon mieux) :
    Je suis donc dans SAS Enterprise Guide (en mode "proc SQL"), et voici l'idée :

    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
    ALTER TABLE MaTable
    	ADD COMBINAISON CHAR(100);
     
    	UPDATE MaTable
    	SET COMBINAISON = 
    		with calcul
        		AS  (   select C1,
    						C2,
    						C3,
    						C4,
    						C5,
    						C6,
     
    					CASE WHEN C1 > 0
    						THEN 'Col C1,' ELSE '' END
                    		||  CASE WHEN C2 > 0
    						THEN 'Col C2,' ELSE '' END
    				||  CASE WHEN C3 > 0
    						THEN 'Col C3,' ELSE '' END
    				||  CASE WHEN C4 > 0
    						THEN 'Col C4,' ELSE '' END
    				||  CASE WHEN C5 > 0
    						THEN 'Col C5,' ELSE '' END
    				||  CASE WHEN C6 > 0
    						THEN 'Col C6,' ELSE '' END
    				AS liste
                	FROM MaTable
            )
    		SELECT  C1,
    						C2,
    						C3,
    						C4,
    						C5,
    						C6, 
    		CASE WHEN charlength(liste) > 0
                THEN SUBSTRING(liste FROM 1 FOR charlength(liste) - 1)
                ELSE ''
            END
    	from    calcul;

    Et l'erreur dont je parlais hier se situe juste à l'endroit où j'écris "with".
    J'ignore si c'est plus clair ?

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 133
    Points : 38 556
    Points
    38 556
    Billets dans le blog
    9
    Par défaut
    Il est possible que votre logiciel ne connaisse pas les Common Table Expression (CTE) déclarées par "WITH"

    Si le moteur SQL sous-jacent est Access ou MySQL dans une version inférieure à la V8, les CTE ne sont pas acceptées.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    Merci pour cette réponse additionnelle.
    Alors comme je suis sous SAS (donc "proc sql"), voici ce que je vais faire :
    1) je vais poster ici ce lien qui parle des CTE dans Sas/proc Sql : https://communities.sas.com/t5/SAS-P.../407313/page/2

    2) notamment ce passage est intéressant :
    Nom : WithProcSQL_001.PNG
Affichages : 198
Taille : 9,9 Ko

    3) et dès que je pourrai tester cela, je reviendrai ici pour indiquer le résultat et cocher "résolu" (en espérant que cela aide d'autres personnes qui travaillent dans l'environnement SAS Enterprise Guide)

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Re-bonjour,

    Alors voici le code auquel j'ai abouti. Il ne comporte pas d'erreur de syntaxe, mais tourne sans arrêt...
    SVP auriez-vous une idée pour optimiser la requête ? (j'ai laissé mes commentaires au cas où)

    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
    /* On cree une copie pour l'update, car on ne peut
    pas mettre a jour une table avec elle-meme : */
    	create table COPIE_DE_LA_TABLE
    	AS select *
    	FROM MaTable;
     
    	/* "ALTER + UPDATE" pour definir
    	les combinaisons : */
    	ALTER TABLE MaTable
    	ADD COMBINAISON CHAR(100);
     
    	/* "WITH" ne fonctionne pas avec
    	SAS/Proc SQL ==> on s'adapte. */
    	UPDATE MaTable
    	SET COMBINAISON =
     
    		(SELECT
    		/* LENGTH est l'équivalent de CHARLENGTH */
    		CASE WHEN LENGTH(liste) > 0
     
    			/* Ici argument depart = 1, et
    			argument arrivee = length - 1 */
                THEN SUBSTR(liste, 1,
    					LENGTH(liste) - 1)
                ELSE ''
            END
     
    		FROM (   select 
    					CASE WHEN C1 > 0
    						THEN 'C1,' ELSE '' END
                    		||  CASE WHEN C2 > 0
    						THEN 'C2,' ELSE '' END
    				||  CASE WHEN C3 > 0
    						THEN 'C3,' ELSE '' END
    				||  CASE WHEN C4 > 0
    						THEN 'C4,' ELSE '' END
    				||  CASE WHEN C5 > 0
    						THEN 'C5,' ELSE '' END
    				||  CASE WHEN C6 > 0
    						THEN 'C6,' ELSE '' END
    				AS liste
     
    				/* C'est la que va nous servir la copie : */
                	FROM COPIE_DE_LA_TABLE
    				WHERE MaTable.NumeroDeLigne
    					= COPIE_DE_LA_TABLE.NumeroDeLigne
            )	)
    ;

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    On cree une copie pour l'update, car on ne peut pas mettre a jour une table avec elle-meme
    archi-faux.

    ADD COMBINAISON CHAR(100);
    Pourquoi un CHAR vu que la longueur est variable.
    Pourquoi 100 puisque la longueur maximale de la combinaison va être 17 ?

    "WITH" ne fonctionne pas avec SAS/Proc SQL ==> on s'adapte.
    Sur le même lien que vous avez publié, il y a aussi tout le détail du passthrough query qui envoie l'ordre "tel quel" à la base de données.

    Et enfin, ce que al1_24 vous a proposé c'est une sélection, pas une mise à jour.
    Ce que vous devez écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    update MaTable
       set Combinaison = trim(trailing ',' from case when C1 > 0 then 'C1,' else '' end
                                             || case when C2 > 0 then 'C2,' else '' end
                                             || case when C3 > 0 then 'C3,' else '' end
                                             || case when C4 > 0 then 'C4,' else '' end
                                             || case when C5 > 0 then 'C5,' else '' end
                                             || case when C6 > 0 then 'C6,' else '' end);

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Bonjour Waldar,

    Merci, cela fonctionne en effet ! Cela permet d'éviter l'update et la sous-requête.

    Juste un détail : concernant ma remarque quand je parlais de la table mise à jour avec elle-même, je faisais référence à un message d'erreur obtenu sur proc SQL, que malheureusement je n'ai plus en tête, mais qui me reprochait d'updater la table avec elle-même (peut-être l'ai-je mal interprété ?)

    Je marque cela en résolu. Encore merci à tous les participants.

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

Discussions similaires

  1. [XL-2007] Recherche d'une valeur dans une ligne en fonction valeur combobox d'un userform
    Par celthi dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 15/06/2015, 21h25
  2. Réponses: 5
    Dernier message: 31/05/2015, 20h57
  3. [XL-2007] Retirer un ligne en fonction des valeurs d'une colonne
    Par CaraLePoke dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 09/10/2012, 18h14
  4. enregistrer en fonction des noms de colonnes
    Par jeff6868 dans le forum R
    Réponses: 2
    Dernier message: 26/04/2012, 17h28
  5. [PROC TABULATE / REPORT] Colorier les lignes en fonction d'un critère
    Par joyeux_lapin13 dans le forum ODS et reporting
    Réponses: 10
    Dernier message: 03/03/2011, 18h27

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