Vous n'êtes pas identifié(e).
Bonjour,
Je dispose d'une table (ma_table) comportant des champs (profondeur,doc,chla) définis avec un type real.
Je fais un insert de données avec la syntaxe suivante:
"insert into ma_table (id_station,profondeur,doc,chla) VALUES (99615,41.4,98.908,0.2951);"
Lorsque j'essaie de retrouver ces données :
Un "select id_station,doc,chla from ma_table where profondeur=41.4;" ne retourne rien ...
Mais " select id_station,doc,chla from ma_table where profondeur='41.4';" fonctionne ...
Pourquoi ai je besoin de mettre des quotes autour de ma valeur décimale pour que le select me retourne mes entrées ? une histoire de stockage d'un arrondi de ma valeur ?
Le format real choisi n'est peut être alors pas adapté si je peux effectuer ce genre d'égalité stricte ?
Faut il systématiquement mettre la valeur ciblée dans mon select entre ' ' pour être certain de ne rien rater lors de la requête ??
Merci d'avance pour vos éclaircissements à ce propos.
Xavier
Hors ligne
Pourquoi ai je besoin de mettre des quotes autour de ma valeur décimale pour que le select me retourne mes entrées ? une histoire de stockage d'un arrondi de ma valeur ?
Un real n'est pas l'idéal pour des comparaisons et des calculs stricts. Le problème est en effet certainement un problème d'arrondi et de type de données
Le format real choisi n'est peut être alors pas adapté si je peux effectuer ce genre d'égalité stricte ?
Tout dépend de ce que vous voulez faire. Mais en soit, les types real (ou float4) et double precision (ou float8) ne permettent pas de comparaison et de calcul stricts. Il faut mieux passer par numeric, plus lent mais plus sûr.
Faut il systématiquement mettre la valeur ciblée dans mon select entre ' ' pour être certain de ne rien rater lors de la requête ??
Non, pas forcément. Tout dépend de ce que vous cherchez. Quand vous écrivez "where champ = 41.4", vous ne précisez pas le type de données de champ et il doit donc le deviner. Il peut choisir numeric, float4 ou float8. Pour ne pas perdre en précision, il prendra le plus gros, avec float8, ce que nous indique d'ailleurs la commande EXPLAIN ;:
? on postgres@r15 =# explain select id_station,doc,chla from ma_table where profondeur=41.4;
┌──────────────────────────────────────────────────────────┐
│ QUERY PLAN │
├──────────────────────────────────────────────────────────┤
│ Seq Scan on ma_table (cost=0.00..33.12 rows=9 width=12) │
│ Filter: (profondeur = '41.4'::double precision) │
└──────────────────────────────────────────────────────────┘
(2 rows)
Avec les problèmes d'arrondi des types float4 (real) et float8 (double precision), il y a de fortes chances que la comparaison indique une inégalité. Si on le mettait de force en float4, la comparaison renvoie une égalité. Par exemple, ces quelques tests ;:
? on postgres@r15 =# select 41.4::float4=41.4::float4;
┌──────────┐
│ ?column? │
├──────────┤
│ t │
└──────────┘
(1 row)
? on postgres@r15 =# select 41.4::float8=41.4::float8;
┌──────────┐
│ ?column? │
├──────────┤
│ t │
└──────────┘
(1 row)
? on postgres@r15 =# select 41.4::float4=41.4::float8;
┌──────────┐
│ ?column? │
├──────────┤
│ f │
└──────────┘
(1 row)
Utiliser les guillemets sans contraindre le type semble quand même le convertir en real/float4.
? on postgres@r15 =# explain select id_station,doc,chla from ma_table where profondeur='41.4';
┌──────────────────────────────────────────────────────────┐
│ QUERY PLAN │
├──────────────────────────────────────────────────────────┤
│ Seq Scan on ma_table (cost=0.00..33.12 rows=9 width=12) │
│ Filter: (profondeur = '41.4'::real) │
└──────────────────────────────────────────────────────────┘
(2 rows)
Je ne suis pas certain que cela soit marqué dans le dur ceci dit. Mieux vaut contraindre le type de données pour s'assurer d'une requête exécutée de façon identique partout ailleurs.
Donc pour moi, soit vous changez le type de données par numeric, soit vous convertissez vos valeurs dans le type de données de la colonne (ça peut devenir problématique si elles changent de type).
Guillaume.
Hors ligne
Merci beaucoup pour cette réponse détaillée ! Qui m'aura permis au passage de découvrir la commande explain que je ne connaissais pas.
Je garde ça en tête pour mes futures requêtes .. et prendrai garde lorsqu'il me faudra tester une égalité !
Xavier
Hors ligne