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 :

SI la sous-requête retourne plusieurs résultats, ALORS


Sujet :

Langage SQL

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut SI la sous-requête retourne plusieurs résultats, ALORS
    Bonjour à tous,

    Après avoir essayé de nombreuses méthodes et syntaxes différentes je n'arrive pas résoudre mon problème, c'est pour cette raison que je m'adresse à vous.

    Voici le code de ma requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    UPDATE art
    SET [Code rayon] = (SELECT
    					CASE WHEN [Type référence externe] = 1 THEN [Référence externe]
    						ELSE CASE WHEN [Type référence externe] = 13 THEN [Référence externe]
    							ELSE CASE WHEN [Type référence externe] = 14 THEN [Référence externe]
    								ELSE 'Non renseigné'
    							END
    						END
    					END 
    				FROM [BDD].[Référence externe article] as rea
    				WHERE rea.[N° article] = art.[N°] and rea.Company = art.Company)
    FROM [BDD].[Article] as art
    Normalement, cette requête doit fonctionner telle quelle car nous possédons une relation 1-1. Cependant, comme il y a eu des erreurs de saisies, il peut y avoir plusieurs résultats qui sont retournés par la sous-requête. Cependant, je ne souhaite pas faire un TOP 1. Ce que je souhaite faire, c'est une requête qui ferait la chose suivante :

    Si la sous-requête retourne plusieurs résultats, alors je modifie [Code rayon] en insérant la chaîne de caractère "Plusieurs résultats possibles", sinon (donc si la sous requête retourne un seul résultat) appliquer le traitement normal présent ci-dessus.

    Comme déjà dit, j'ai essayé avec des count, des @@rowcount... mais j'ai pas réussi à obtenir le résultat voulu.

    Je vous remercie d'avance pour votre aide

    PS : Le SGBD utilisé est SQL Server 2008 R2.

    Vivien

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 154
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Avec MERGE, tu devrais pouvoir lancer deux requête UPDATE différentes en fonction d'un critère. J'imagine que la solution passer par là.

    Sinon, il faudra un bloc de script plutôt qu'une simple requête.

    Ou alors faire une usine à gaz ^^
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut
    Tout d'abord merci pour ta réponse rapide.

    Tu aurais une idée de comment faire 2 updates différents en fonction d'un critère avec l'instruction de MERGE ?

    Pour un script tu utiliserais un curseur ?

    Je te remercie.

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Vous pouvez faire comme ceci (à adapter peut-être, mais le principe est là) :

    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 CTE AS (
    	SELECT 
    		[Code rayon] 
    		,[Référence externe] 
    		,COUNT([Référence externe]) OVER (PARTITION BY rea.[N° article], rea.Company) as NbRef
    	FROM [BDD].[Article] AS art
    	LEFT OUTER JOIN [BDD].[Référence externe article] AS rea
    		ON rea.[N° article] = art.[N°] 
    		AND rea.Company = art.Company 
    		AND [Type référence externe] IN (1,13,14)
    )
    UPDATE CTE 
    	SET	[Code rayon] = 
    		CASE NbRef	
    			WHEN 0 THEN 'Non renseigné'
    			WHEN 1 THEN [Référence externe] 
    			ELSE 'Plusieurs résultats possibles'
    		END
    Cas particulier : si vous avez plusieurs saisies avec toujours les même valeurs, il peut être judicieux de considérer tout de même cette valeur comme correcte. Vous pouvez alors faire ainsi :

    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
     
     
     
    WITH CTE AS (
    	SELECT 
    		[Code rayon] 
    		,MIN([Référence externe]) OVER (PARTITION BY rea.[N° article], rea.Company) as MinRef
    		,MAX([Référence externe]) OVER (PARTITION BY rea.[N° article], rea.Company) as MaxRef
    	FROM [BDD].[Article] AS art
    	LEFT OUTER JOIN [BDD].[Référence externe article] AS rea
    		ON rea.[N° article] = art.[N°] 
    		AND rea.Company = art.Company 
    		AND [Type référence externe] IN (1,13,14)
    )
    UPDATE CTE 
    	SET	[Code rayon] = 
    		CASE	
    			WHEN MinRef = MaxRef THEN MinRef
    			WHEN MinRef <> MaxRef THEN 'Plusieurs résultats possibles'
    			ELSE 'Non renseigné'
    		END

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut
    Merci bien pour votre réponse complète.

    J'ai cependant une petite question, car je ne connais pas trop le fonctionnement de OVER...PARTITION.

    Votre code tient-il compte de la gestion des CASE WHEN en cascade comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CASE WHEN [Type référence externe] = 1 THEN [Référence externe]
    	ELSE CASE WHEN [Type référence externe] = 13 THEN [Référence externe]
    		ELSE CASE WHEN [Type référence externe] = 14 THEN [Référence externe]
    			ELSE 'Non renseigné'
    		END
    	END
    END
    Car en faite, pour un article donnée, il peut y avoir une référence externe à 1, 13 et 14. Dans ce cas, on prendra toujours la Référence externe correspondant à 1 en priorité, si il n'y a pas de 1, on prendra celle à 13 etc... Donc la règle de gestion par importance est la suivante 1>13>14>Non renseigné

    Je vous remercie d'avance.

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    CASE WHEN [Type référence externe] = 1 THEN [Référence externe]
    	ELSE CASE WHEN [Type référence externe] = 13 THEN [Référence externe]
    		ELSE CASE WHEN [Type référence externe] = 14 THEN [Référence externe]
    			ELSE 'Non renseigné'
    		END
    	END
    END
    est équivalent à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    CASE WHEN [Type référence externe] IN (1, 13, 14) THEN [Référence externe] ELSE  'Non renseigné' END
    Car si [Type référence externe] est égal = 13, alors il ne peut pas être égal à 1...

    Cependant, en lisant votre explication, je pense qu'il y a un souci dans votre requete initiale.
    Un jeu d'essai plus résultat attendu seraient les bienvenus pour être sûr de bien se comprendre.

  7. #7
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut
    Voici le un select sur la table Référence externe article pour un article donné (la valeur 2 du champ type référence externe remplace la valeur 1 dans cet exempleà :

    Nom : imag.png
Affichages : 892
Taille : 16,7 Ko

    Nous sommes dans le cas d'une erreur de saisie, car pour un article donné et un type de référence externe nous avons plusieurs lignes, donc pour cet article, le code rayon doit être modifié en "Plusieurs résultats possibles".

    Admettons que la requête renvoie le résultat suivant (s'il n'y avait pas eu d'erreurs)

    Nom : imag.png
Affichages : 894
Taille : 8,5 Ko

    Comme 2 a la priorité sur 14, dans Code Rayon nous injecterons la valeur "SEM CHEVRON..." et pas "1512845".

    Je vous remercie encore pour votre aide

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    et si vous avez deux lignes avec [Type référence externe] = 2 mais une seule avec [Type référence externe] = 14 ?

  9. #9
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut
    Dans ce cas on assigne également la valeur "Plusieurs résultats possibles".

    On aurait pris la valeur correspondante au 14 uniquement s'il n'y avait pas eu de ligne avec [type référence externe] à 2.

  10. #10
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Alors quelque chose comme ceci (pas testé)

    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
     
    WITH CTE AS (
    	SELECT 
    		[Code rayon] 
    		,MIN([Référence externe]) OVER (PARTITION BY rea.[N° article], rea.Company, [Type référence externe]) as MinRef
    		,MAX([Référence externe]) OVER (PARTITION BY rea.[N° article], rea.Company, [Type référence externe]) as MaxRef
    		,RANK() OVER(
    					PARTITION BY rea.[N° article], rea.Company 
    					ORDER BY 
    						CASE [Type référence externe]
    							WHEN 1 THEN 1
    							WHEN 13 THEN 2
    							WHEN 14 THEN 3
    						END
    					) AS Rang
    	FROM [BDD].[Article] AS art
    	LEFT OUTER JOIN [BDD].[Référence externe article] AS rea
    		ON rea.[N° article] = art.[N°] 
    		AND rea.Company = art.Company 
    		AND [Type référence externe] IN (1,13,14)
    )
    UPDATE CTE 
    	SET	[Code rayon] = 
    		CASE	
    			WHEN MinRef = MaxRef THEN MinRef
    			WHEN MinRef <> MaxRef THEN 'Plusieurs résultats possibles'
    			ELSE 'Non renseigné'
    		END
    WHERE Rang = 1
    notez qu'on pourrait se passer du CASE dans la clause d'ordonnancement car l'ordre "fonctionel" correspond à l'ordre numérique...

  11. #11
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2012
    Messages
    345
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2012
    Messages : 345
    Points : 103
    Points
    103
    Par défaut
    Je vous remercie, je vais faire une batterie de test pour voir si l'on obtient bien le résultat voulu.

    Une petite erreur, je pense, dans le dernier case il faut assigner [Référence externe] au lien de MinRef.

    Merci encore pour votre dévouement.

  12. #12
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Citation Envoyé par italia57 Voir le message
    Une petite erreur, je pense, dans le dernier case il faut assigner [Référence externe] au lien de MinRef.
    [Référence externe] n'est directement dans la CTE, donc ça ne fonctionnera pas. Vous pouvez en effet l'ajouter, mais c'est inutile.

    Comme vous n'aviez pas précisé, suite à ma remarque, que faire lorsqu'il il y plusieurs ligne mais qu'elles ont toutes la même valeurs, j'ai adpaté la seconde requete.
    Dans cette requête, lorsqu'on fait appel a minRef, c'est uniquement lorsqu'il est égal a maxRef (donc qu'il n'y a qu'une seule valeur). donc minRef me semble correct.

    Bien sûr, on pourrait reprendre la première requête que j'avais proposée et ajouter un DISTINCT dans le COUNT, ce qui aurait a priori le même effet...

    Vous pouvez donc aussi reprendre la première requete, et ajouter de la même façon le test sur le rang.

Discussions similaires

  1. Sous-requête avec plusieurs résultats souhaités
    Par devlm dans le forum Requêtes
    Réponses: 3
    Dernier message: 19/08/2014, 12h02
  2. Réponses: 6
    Dernier message: 11/05/2012, 10h38
  3. Sous-requête excutée plusieurs fois dans une requête
    Par sheridan31 dans le forum Oracle
    Réponses: 8
    Dernier message: 03/07/2006, 16h18
  4. Savoir si une requête retourne un résultat ou pas
    Par zut94 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 30/09/2005, 15h48
  5. Une fonction peut-elle retourner plusieurs résultats ?
    Par aragorns dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 26/03/2005, 22h18

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