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

Développement SQL Server Discussion :

[Requete] Probleme avec double jointure et cast


Sujet :

Développement SQL Server

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

    Informations forums :
    Inscription : Janvier 2008
    Messages : 9
    Points : 6
    Points
    6
    Par défaut [Requete] Probleme avec double jointure et cast
    Bonsoir à tous,

    Je rencontre actuellement un souci dans l'execution d'une requete.

    Le contexte :
    1 table T_ITEMS_ITM contenant :
    -ITM_ID (int) clef primaire

    1 table T_ATTRIBUTS_ATT contenant :
    -ATT_ID (int) clef primaire
    -ATT_LIBELLE (varchar(20))

    1 table TJ_ATT_ITM_VALUES_ATI contenant :
    -ITM_ID (int) clef etrangere
    -ATT_ID (int) clef etrangere
    -ATI_VALEUR (varchar(512))


    La dernière table contient en clefs étrangères les clefs primaires des deux précédentes tables ainsi que la valeur lié à l'attribut de l'item spécifié.

    les attributs sont (entre autre) PrixVenteTTC et PrixAchatTTC

    Ainsi lorsque j'interroge ma table pour récuperer les prix de vente ou d'achat je suis obligé de caster ATI_VALEUR de maniere a pouvoir comparer les valeurs.. Et c'est la que se pose le souci.

    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
     
     
    select Item.ITM_ID 
    		from T_ITEMS_ITM as Item 
     
    		inner join TJ_ATT_ITM_VALUES_ATI as ValeurPrixVente on ValeurPrixVente.ITM_ID = Item.ITM_ID 
    		inner join T_ATTRIBUTS_ATT as AttPrixVente on AttPrixVente.ATT_ID = ValeurPrixVente.ATT_ID
     
    		inner join TJ_ATT_ITM_VALUES_ATI as ValeurPrixAchat on ValeurPrixAchat.ITM_ID = Item.ITM_ID 
    		inner join T_ATTRIBUTS_ATT as AttPrixAchat on AttPrixAchat.ATT_ID = ValeurPrixAchat.ATT_ID
     
    		where	
    		AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' and 
    		cast( ValeurPrixVente.ATI_VALEUR as int) >= 380 and	
     
    		AttPrixAchat.ATT_LIBELLE = 'PrixAchatTtc' and 
    		cast( ValeurPrixAchat.ATI_VALEUR as money) >= 180
    J'ai aussi essayer ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    select Item.ITM_ID 
    		from T_ITEMS_ITM as Item 
     
    		inner join TJ_ATT_ITM_VALUES_ATI as ValeurPrixVente on ValeurPrixVente.ITM_ID = Item.ITM_ID and cast( ValeurPrixVente.ATI_VALEUR as money) >= 380
    		inner join T_ATTRIBUTS_ATT as AttPrixVente on AttPrixVente.ATT_ID = ValeurPrixVente.ATT_ID and AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc'
     
    		inner join TJ_ATT_ITM_VALUES_ATI as ValeurPrixAchat on ValeurPrixAchat.ITM_ID = Item.ITM_ID and cast( ValeurPrixAchat.ATI_VALEUR as money) >= 180
    		inner join T_ATTRIBUTS_ATT as AttPrixAchat on AttPrixAchat.ATT_ID = ValeurPrixAchat.ATT_ID and AttPrixAchat.ATT_LIBELLE = 'PrixAchatTtc'

    L'erreur est la suivante :
    Msg 245, Niveau 16, État 1, Ligne 3
    Échec de la conversion de la valeur varchar 'BA003348' en type de données money.


    'BA003348' étant la valeur d'un autre attribut (representant le code de mon produit).

    Ce que je ne comprend pas, c'est que le cast tente de s'effectuer sur une valeur d'attribut que je n'ai pas spécifier dans la jointure.

    De plus, si je vire la jointure correspondant au prix d'achat, la requête s'exécute sans erreur...

    Voila, si quelqu'un pouvait m'aiguiller, je galeres pas mal et je ne comprend absolument pas d'ou vient le probleme ...

    Merci beaucoup à tous.

    NB: Je suis sous SQL Server 2008 Express Edition

  2. #2
    Membre confirmé Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Points : 478
    Points
    478
    Par défaut Il n'y a pas d'ordre d'évaluation
    Bonjour,

    Quand vous faites,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    WHERE	
    		AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' AND 
    		cast( ValeurPrixVente.ATI_VALEUR AS int) >= 380
    Il y a toujours évaluation de la seconde condition, même si le libellé n'est pas le prix de vente.

    SQL est un langage déclaratif, pour le forcer à restreindre d'abord sur les métadonnées de prix, vous pouvez effectuer les jointures sur des sous requêtes ne ramenant que les libellés de type prix.

    Pour votre second essai, dans une jointure droite, cela revient au même de mettre la condition dans le JOIN ou dans le WHERE.

    @+

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

    Informations forums :
    Inscription : Janvier 2008
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par agemis31 Voir le message
    Bonjour,

    Quand vous faites,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    WHERE	
    		AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' AND 
    		cast( ValeurPrixVente.ATI_VALEUR AS int) >= 380
    Il y a toujours évaluation de la seconde condition, même si le libellé n'est pas le prix de vente.

    SQL est un langage déclaratif, pour le forcer à restreindre d'abord sur les métadonnées de prix, vous pouvez effectuer les jointures sur des sous requêtes ne ramenant que les libellés de type prix.

    Pour votre second essai, dans une jointure droite, cela revient au même de mettre la condition dans le JOIN ou dans le WHERE.

    @+
    Bonjour, et merci beaucoup de votre réponse.

    Néanmoins, je ne comprend pas un point.

    Comment se fait-il que ma jointure et mon where fonctionne si je supprime le second ensemble de jointure ?
    Dans le premier exemple que j'ai donné, si je ne laisse que ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT Item.ITM_ID 
    		FROM T_ITEMS_ITM AS Item 
     
    		INNER JOIN TJ_ATT_ITM_VALUES_ATI AS ValeurPrixVente ON ValeurPrixVente.ITM_ID = Item.ITM_ID 
    		INNER JOIN T_ATTRIBUTS_ATT AS AttPrixVente ON AttPrixVente.ATT_ID = ValeurPrixVente.ATT_ID
     
    		WHERE	
    		AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' AND 
    		cast( ValeurPrixVente.ATI_VALEUR AS int) >= 380
    La requête s'exécute sans souci, c'est le fait de faire la jointure sur plusieurs attributs qui semble poser souci.

    Or d'après ce que vous me dites, la seconde condition est testé et ceci en dehors de l'évaluation de la première condition (évaluation du nom de l'attribut).

    Cela semble vrai dans le cas de la double jointure et double cast, mais pas dans le cas d'une unique jointure...


    Merci encore de votre temps

  4. #4
    Membre confirmé Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Points : 478
    Points
    478
    Par défaut Ca dépend aussi de vos données
    Si vous n'avez que des valeurs transformables en int (via cast) dans vos données, ça va marcher !

    Ceci, par exemple, soulève l'erreur
    Échec de la conversion de la valeur varchar 'pas un int' en type de données int.


    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
    declare @T_ITEMS_ITM table (itm_id int)
    insert into @T_ITEMS_ITM select 1
     
    declare @T_ATTRIBUTS_ATT table (att_id int, att_libelle varchar(20))
    insert into @T_ATTRIBUTS_ATT select 1, 'PrixVenteTtc'
    insert into @T_ATTRIBUTS_ATT select 2, 'Pas un prix'
     
    declare @TJ_ATT_ITM_VALUES_ATI table(itm_id int, att_id int, ati_valeur varchar(512))
    insert into @TJ_ATT_ITM_VALUES_ATI select 1, 1,  '381'
    insert into @TJ_ATT_ITM_VALUES_ATI select 1, 2,  'pas un int'
     
    SELECT Item.ITM_ID 
    FROM @T_ITEMS_ITM AS Item 
    INNER JOIN @TJ_ATT_ITM_VALUES_ATI AS ValeurPrixVente ON ValeurPrixVente.ITM_ID = Item.ITM_ID 
    INNER JOIN @T_ATTRIBUTS_ATT AS AttPrixVente ON AttPrixVente.ATT_ID = ValeurPrixVente.ATT_ID	
    WHERE	
    	AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' 
    AND 
    	cast( ValeurPrixVente.ATI_VALEUR AS int) >= 380
    @+

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

    Informations forums :
    Inscription : Janvier 2008
    Messages : 9
    Points : 6
    Points
    6
    Par défaut
    Alors la c'est très étonnant...

    Quand je prend votre requête de sélection et que j'enlève les '@', cela marche parfaitement dans ma base, et je n'ai aucune erreur de conversion. (j'ai remplacé 'int' par 'float' pour le cast étant donné que je stock des nombres décimaux).

    Bizarre que cela marche dans ma base alors que j'ai 15 types d'attributs différents, allant du stockage d'url au prix de vente...

    Mais par contre si je fait la même requête avec votre jeu de test, effectivement la requête produit une erreur...

    Plus j'avance, plus je suis perdu

  6. #6
    Membre confirmé Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Points : 478
    Points
    478
    Par défaut
    Bonjour,

    Est ce que ceci fonctionne chez vous ?

    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
    SELECT ITM_ID, 
    	   CASE ATT_LIBELLE 
    	   WHEN 'PrixAchatTtc' THEN CAST(A.ATI_VALEUR AS FLOAT) 
    	   ELSE NULL
    	   END AS PrixAchatTTC,	   
    	   CASE ATT_LIBELLE 
    	   WHEN 'PrixVenteTtc' THEN CAST(A.ATI_VALEUR AS FLOAT) 
    	   ELSE NULL
    	   END AS PrixVenteTTC	   
    FROM
    (SELECT Item.ITM_ID, AttPrixVente.ATT_LIBELLE, ValeurPrixVente.ATI_VALEUR 
    FROM T_ITEMS_ITM Item 
    INNER JOIN TJ_ATT_ITM_VALUES_ATI ValeurPrixVente ON 
    Item.ITM_ID = ValeurPrixVente.ITM_ID
    INNER JOIN T_ATTRIBUTS_ATT AttPrixVente ON 
    AttPrixVente.ATT_ID = ValeurPrixVente.ATT_ID
    WHERE 
    	AttPrixVente.ATT_LIBELLE = 'PrixVenteTtc' OR AttPrixVente.ATT_LIBELLE = 'PrixAchatTtc' 
    ) A 
    WHERE 
    	CASE ATT_LIBELLE 
    	WHEN 'PrixVenteTtc' THEN CAST(A.ATI_VALEUR AS FLOAT) 
    	ELSE NULL
    	END >= 380
    @+

Discussions similaires

  1. Réponses: 5
    Dernier message: 03/09/2007, 13h52
  2. [HQL]Problème avec double join fetch
    Par zev dans le forum Hibernate
    Réponses: 1
    Dernier message: 05/12/2006, 09h59
  3. [DB2] Problèmes avec une Jointure externe sur des vues
    Par treivse dans le forum Langage SQL
    Réponses: 6
    Dernier message: 11/07/2006, 11h42
  4. requete avec double jointure externe
    Par cdu dans le forum Langage SQL
    Réponses: 8
    Dernier message: 04/01/2006, 14h54
  5. [jointure]requete possible de double jointure entre 2 tables
    Par akira_le_gaucher dans le forum Langage SQL
    Réponses: 4
    Dernier message: 11/05/2004, 15h03

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