Mysql 5 : Tri sur nombres négatifs

Consultez la formation à Google Analytics de WebRankInfo / Ranking Metrics

Robinson
WRInaute passionné
WRInaute passionné
 
Messages: 2233
Inscription: 25 Oct 2005

Mysql 5 : Tri sur nombres négatifs

Message le Sam Jan 26, 2008 18:24

Bonjour,

J'ai un petit problème sur une requête de tri.

Elle doit trier un résultat d'un petit calcul sur deux colonnes.

ORDER BY (colonne1 * 5 - colonne2 * 3) DESC

Ces deux colonnes sont de type UNSIGNED.
Problème, il considère les nombres négatifs comme supérieurs...

Avec mysql 4, cela fonctionnait sans problème. Avez-vous une solution svp ? Merci.

jcaron
WRInaute accro
WRInaute accro
 
Messages: 2685
Inscription: 13 Fév 2004

Re: Mysql 5 : Tri sur nombres négatifs

Message le Sam Jan 26, 2008 19:10

Robinson a écrit:J'ai un petit problème sur une requête de tri.

Elle doit trier un résultat d'un petit calcul sur deux colonnes.

ORDER BY (colonne1 * 5 - colonne2 * 3) DESC

Ces deux colonnes sont de type UNSIGNED.
Problème, il considère les nombres négatifs comme supérieurs...

Avec mysql 4, cela fonctionnait sans problème. Avez-vous une solution svp ? Merci.


Au moins solutions:
- convertir en signed d'abord (cast(colonne1 as signed)..)
- ajouter une grande valeur (supérieure à la valeur absolue de la différence la plus petite) *avant* de soustraire, pour que le résultat reste positif (par exemple 10000 + colonne1*5 - colonne2*3)

Il doit y en avoir d'autres...

Jacques.

Robinson
WRInaute passionné
WRInaute passionné
 
Messages: 2233
Inscription: 25 Oct 2005

Message le Sam Jan 26, 2008 19:52

Merci, je vais utiliser la seconde solution :)

FlorentP
WRInaute discret
WRInaute discret
 
Messages: 145
Inscription: 25 Juin 2005

Message le Dim Jan 27, 2008 9:13

Ou reporter le bug a mysql :d


ecocentric
WRInaute accro
WRInaute accro
 
Messages: 3602
Inscription: 10 Fév 2004

Message le Dim Jan 27, 2008 9:39

idée bête: tu as essayé de mettre un alias dans le SELECT et d'utiliser l'alias dans l'ORDER BY ?

jcaron
WRInaute accro
WRInaute accro
 
Messages: 2685
Inscription: 13 Fév 2004

Message le Dim Jan 27, 2008 11:32

FlorentP a écrit:Ou reporter le bug a mysql :d


Je ne vois pas où est le bug, si on travaille avec des entiers non signés, et que le résultat d'une opération est négatif, forcément ça donne des choses pas très prévisibles, rien de plus normal.

Jacques.

Robinson
WRInaute passionné
WRInaute passionné
 
Messages: 2233
Inscription: 25 Oct 2005

Message le Dim Jan 27, 2008 13:53

ecocentric a écrit:idée bête: tu as essayé de mettre un alias dans le SELECT et d'utiliser l'alias dans l'ORDER BY ?

Oui et c'est la même chose.

jcaron, pourquoi cela fonctionnait dans les versions mysql précédentes ?
Pas besoin de me répondre, je pense avoir une idée, comme php, les deux se veulent de plus en plus professionnels et donc de plus en plus tatillons et respectueux des normes de développement ^^

FlorentP
WRInaute discret
WRInaute discret
 
Messages: 145
Inscription: 25 Juin 2005

Message le Dim Jan 27, 2008 14:14

jcaron a écrit:
FlorentP a écrit:Ou reporter le bug a mysql :d


Je ne vois pas où est le bug, si on travaille avec des entiers non signés, et que le résultat d'une opération est négatif, forcément ça donne des choses pas très prévisibles, rien de plus normal.

Jacques.

Ce n'est pas parceque les chiffres qu'il manipule sont non signés que le résultat doit l'être...
C'est comme si tu disais que mysql devait te retourner un résultat entre 0 et 255 si on faisait des opérations à partir d'un tinyint. Un tinyint multiplié par un autre, ya pas de raison qu'il reste borné dans un tinyint. Idem pour des opérations avec des unsigned.

jcaron
WRInaute accro
WRInaute accro
 
Messages: 2685
Inscription: 13 Fév 2004

Message le Dim Jan 27, 2008 15:19

FlorentP a écrit:Ce n'est pas parceque les chiffres qu'il manipule sont non signés que le résultat doit l'être...


Dans tous les langages que je connais, y compris SQL, le résultat d'une opération sur deux valeurs d'un type X est presque systématiquement (voire même tout le temps?) dans le même type X. C'est totalement volontaire, et ce n'est pas un bug, même s'il y a au moins un bug report par mois (refermé aussi vite) comme quoi postgresql est buggé parce qu'il dit que (par exemple) 1 / 2 * 2 = 0. Si tu veux obtenir le "bon" résultat, il faut passer par des floats, mais tu ne veux pas non plus qu'il passe sur des floats pour un oui ou pour un non alors que toi tu voulais qu'il reste sur des entiers... C'est un choix arbitraire, mais c'est comme ça.

D'ailleurs visiblement, ils doivent considérer que le comportement précédent est un bug, et qu'ils l'ont corrigé, il y a un moyen d'avoir l'ancien comportement:

"Si vous rencontrez un problème avec les colonnes UNSIGNED dans vos anciennes applications MySQL lorsque vous effectuez le port sous la version 4.0 de MySQL , vous pouvez utiliser l'option --sql-mode=NO_UNSIGNED_SUBTRACTION lorsque vous lancez mysqld. Notez cependant qu'aussi longtemps que vous employez ceci, vous ne serez pas capable d'utiliser efficacement les colonnes de type UNSIGNED BIGINT."

(from http://dev.mysql.com/doc/refman/5.0/fr/ ... tions.html)

FlorentP a écrit:C'est comme si tu disais que mysql devait te retourner un résultat entre 0 et 255 si on faisait des opérations à partir d'un tinyint. Un tinyint multiplié par un autre, ya pas de raison qu'il reste borné dans un tinyint. Idem pour des opérations avec des unsigned.


Je n'ai pas de serveur mysql sous la main, mais dans postgresql c'est nettement plus clair (mais smallint est sur 16 bits et pas 8 bits, et il n'y a pas de signed/unsigned):

Code: Tout sélectionner
# select 10000::smallint * 10000::smallint;
ERROR:  smallint out of range

# \do
                                                                              Liste des opérateurs
   Schéma   | Nom  |    Type de l'arg. gauche    |    Type de l'arg. droit     |      Type du résultat       |                           Description                           
------------+------+-----------------------------+-----------------------------+-----------------------------+------------------------------------------------------------------
[...]
pg_catalog | *    | smallint                    | smallint                    | smallint                    | multiply


Jacques.

FlorentP
WRInaute discret
WRInaute discret
 
Messages: 145
Inscription: 25 Juin 2005

Message le Dim Jan 27, 2008 17:25

Bon apparement la solution au probleme c'est pas de reporter le changement de comportement a mysql mais de mettre l'option --sql-mode=NO_UNSIGNED_SUBTRACTION...

Pour ce qui est du résultat qui est toujours de type x sur une opération entre deux valeurs de type x : en C, si tu fais
printf("%d",r, unsigned int - unsigned int);
tu peux récupérer des valeures négatives sur ta valeure de retour.
Ce type de traitement doit être assez spécifique à certains langages, et je trouve pas ça super logique que ça fonctionne comme ça par défaut

jcaron
WRInaute accro
WRInaute accro
 
Messages: 2685
Inscription: 13 Fév 2004

Message le Dim Jan 27, 2008 19:20

FlorentP a écrit:Pour ce qui est du résultat qui est toujours de type x sur une opération entre deux valeurs de type x : en C, si tu fais
printf("%d",r, unsigned int - unsigned int);
tu peux récupérer des valeures négatives sur ta valeure de retour.


Parce que %d indique que la valeur est à condidérer comme un signed int. Tu devrais normalement utiliser %u (comme au final la représentation binaire reste la même, et que C ne fait pas d'erreur en cas d'overflow, tu retombes sur tes pattes).

Essaie plutôt ça:

Code: Tout sélectionner
unsigned a,b;
a=10;
b=20
if (a-b < 0)
{
         printf("negatif\n");
}
else
{
        printf("positif\n");
}


FlorentP a écrit:Ce type de traitement doit être assez spécifique à certains langages, et je trouve pas ça super logique que ça fonctionne comme ça par défaut


C'est comme ça en C comme en SQL. Je pense que c'est vrai dans beaucoup de langages fortement typés...

Jacques.

Robinson
WRInaute passionné
WRInaute passionné
 
Messages: 2233
Inscription: 25 Oct 2005

Message le Dim Jan 27, 2008 21:03

Oui, c'est ainsi dans plein de langages, je l'avais déjà vu il y a quelques années (peut-être bien avec Access ou en C, me souviens pu).

Mon ptit BTS commence à remonter à quelques années, me fait vieux :'(
Et cette rigueur de développement, je l'avais un peu zappée avec le php et mysql ^^


Si vous avez aimé cette discussion, partagez-la sur vos réseaux sociaux préférés :

Formation recommandée sur ce thème :

Formation Google Analytics : en 2 jours, apprenez comment exploiter l'essentiel des possibilités de l'outil de mesure d'audience de Google. Formation animée par les experts Google Analytics de Ranking Metrics.

Tous les détails sur le site Ranking Metrics : programme, prix, dates et lieux, inscription en ligne.

Lectures recommandées sur ce thème :



Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité