[SQL] Comment éviter une division par 0 (zéro) --> résolu par DECODE()

Comment éviter une division par 0 (zéro) --> résolu par DECODE() [SQL] - SQL/NoSQL - Programmation

Marsh Posté le 20-09-2004 à 11:18:22    

Bonjour !
 
je voudrai faire un SUM() dans une requête SQL qui contient une division.
 
du style SUM (A/B)
 
Mais il se peut que B soit égal à 0 (mais pas null)
 
Dans ce cas j'ai une erreur :D
 
alors est-ce-qu'il existe une fonction du genre ISZERO() :D ?
 
Merci !


Message édité par camarchepoa le 20-09-2004 à 13:24:33
Reply

Marsh Posté le 20-09-2004 à 11:18:22   

Reply

Marsh Posté le 20-09-2004 à 11:22:22    

Pa spécialement. Par contre, il existe toujours le comparateur classique != (ou <> suivant le SDGB)

Reply

Marsh Posté le 20-09-2004 à 11:38:55    

rajout un where b <>0 dans ta requete !
quel comportement attend-tu si b=0 ?

Reply

Marsh Posté le 20-09-2004 à 11:49:24    

Merci pour ces pistes mais il ne faut pas que j'exclue les lignes ou B=0
 
Si B=0 il faut que SUM(A/B) renvoie 0  
 
je voi vraiment pas moi :(

Reply

Marsh Posté le 20-09-2004 à 11:54:20    

Bonjour,
 
Une requête dans ce genre là pourrait être un début de piste ?
 
select sum(A/B) as Result where B > 0
union
select 0 as Result where B = 0

Reply

Marsh Posté le 20-09-2004 à 12:03:00    

quel sgbd ?
 
avec Oracle, tu as DECODE (je crois qu'il existe aussi en MySQL) :
 
SELECT SUM(DECODE(B, 0, B, A/B))
FROM ...

Reply

Marsh Posté le 20-09-2004 à 12:33:23    

Ce genre de fonctions dépend du RDBMS.
 
Les unions sont à éviter car peu performantes.
 
La solution proposée par Arjuna est plus indiquée. Des fonctions équivalentes existent pour la plupart des RDBMS ("if" plus probablement).


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 20-09-2004 à 12:42:36    

merci pour toutes ces réponses !!
 
 
c'est avec informix ... tout le monde n'est pas à la pointe de la technologie :D
 
je vais voire si DECODE peut fonctionner ;)

Reply

Marsh Posté le 20-09-2004 à 12:45:03    

Petit rappel au niveau des UNION.
 
Le UNION fait de base un DISTINCT, et c'est ça qui consomme énorméménent de ressources, surtout si le nombre de lignes est important et certaines colonnes calculées.
 
Il faut donc systématiquement utilise la clause "UNION ALL", à moins qu'on ait besoin du distinct. En effet, vous pouvez tester, le UNION ALL ne dédoublonne pas les résultats, ce qui le rends infiniment plus rapide qu'un UNION classique.

Reply

Marsh Posté le 20-09-2004 à 12:45:42    

camarchepoa a écrit :

merci pour toutes ces réponses !!
 
 
c'est avec informix ... tout le monde n'est pas à la pointe de la technologie :D
 
je vais voire si DECODE peut fonctionner ;)


Sinon ce sera certainement IF() ou IIF() comme l'a di sircam

Reply

Marsh Posté le 20-09-2004 à 12:45:42   

Reply

Marsh Posté le 20-09-2004 à 12:47:26    

Arjuna a écrit :

Petit rappel au niveau des UNION.
 
Le UNION fait de base un DISTINCT, et c'est ça qui consomme énorméménent de ressources, surtout si le nombre de lignes est important et certaines colonnes calculées.
 
Il faut donc systématiquement utilise la clause "UNION ALL", à moins qu'on ait besoin du distinct. En effet, vous pouvez tester, le UNION ALL ne dédoublonne pas les résultats, ce qui le rends infiniment plus rapide qu'un UNION classique.


Déjà, c'est une bonne remarque.
 
Mais si tu fais un UNION ALL entre deux select, le RDBMS ne va-t-il pas de toute façon exécuter les deux queries séparemment avant d'ensembler un résultat unique, si je ne me trompe ?


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 20-09-2004 à 12:52:32    

Oui en effet. Mais lors d'une requête classique, par exemple :
 
SELECT NOM, PRENOM
FROM UTILISATEUR
WHERE DATE_NAISANCE > '01/01/1980'
 
ton SGBD va prendre 1 ou 2 % pour comprendre la requête et trouver l'index à utiliser.
5 à 20 % pour éxécuter la requête.
Puis tout le reste à construire un curseur pour te rammener les lignes.
 
Avec un UNION ALL, il va donc doubler les deux premières étapes mais la dernière, qui est la plus longue, durera le même temps. La perte de perfs est alors acceptable.
 
Ceci dit, quand on peut éviter un UNION, il faut toujours l'éviter, car en effet ça restera dans tous les cas plus lent qu'une autre solution ;)

Reply

Marsh Posté le 20-09-2004 à 13:23:53    

.
 
merci à tous pour votre aide !
 
ca fonctionne à meveillle avec le DECODE() :)
 
j'édite le titre en conséquence ;)

Reply

Marsh Posté le 20-09-2004 à 13:55:01    

Arjuna a écrit :

Oui en effet. Mais lors d'une requête classique, par exemple :
 
SELECT NOM, PRENOM
FROM UTILISATEUR
WHERE DATE_NAISANCE > '01/01/1980'
 
ton SGBD va prendre 1 ou 2 % pour comprendre la requête et trouver l'index à utiliser.
5 à 20 % pour éxécuter la requête.
Puis tout le reste à construire un curseur pour te rammener les lignes.
 
Avec un UNION ALL, il va donc doubler les deux premières étapes mais la dernière, qui est la plus longue, durera le même temps. La perte de perfs est alors acceptable.
 
Ceci dit, quand on peut éviter un UNION, il faut toujours l'éviter, car en effet ça restera dans tous les cas plus lent qu'une autre solution ;)


Bon à savoir, je ne connaissais pas les proportions entre les différentes étapes. Merci.


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 20-09-2004 à 14:10:54    

les proportins sont loin d'êtres exactes (ça dépends d'énormément de choses).
mais c'est globalement dans ces proportions :
- Le plus long est presque toujours la récupération des donnés une fois la requêtes exécutée, sauf dans le cas où tu as très peu de données évidement
- Ensuite, c'est l'éxécution de la requête. Selon si tu as des jointures externes, des fonctions de regroupement et des sous-requêtes, ça peut changer du tout au tout la vitesse de cette étape
- Et le plus cour c'est évidement le parse de la requête SQL et la recherche des indexes à utiliser.

Reply

Marsh Posté le 20-09-2004 à 14:20:11    

J'aurais tablé sur l'exécution sensu stricto comme facteur déterminant. Maintenant, si les index sont bons et les queries simples, je comprends que cette étape prenne proportionnelement moins de temps.


---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 21-09-2004 à 00:47:02    

sensu stricto, tu parles du parsing et de l'optimisation ?
 
disons que d'un SGBD à l'autre, ça doit changer en effet, mais le parsing est relativement simple, quand à l'optimisation, c'est basé sur des algo "tous fais", donc l'optimiseur n'a qu'à vérifier que la requête contient certains patterns afin d'appliquer la bonne méthode, c'est assez rapide.
 
Ensuite par contre, la lecture des index, les tris, et surtout les regroupements ça bouffe énormément de temps, d'autant plus quand il y a des distinct : une première lecture pour faire un tri temporaire, puis une seconde lecture pour virer les doublons, c'est la mort pour le SGBD. Ensuite, pour la construction du curseur et la récupération des indexes, je pense que ça se passe d'explications, ça extrêment lent, à cause de limitations purement matérielles.

Reply

Marsh Posté le 21-09-2004 à 10:03:21    

Arjuna a écrit :

sensu stricto, tu parles du parsing et de l'optimisation ?
 
disons que d'un SGBD à l'autre, ça doit changer en effet, mais le parsing est relativement simple, quand à l'optimisation, c'est basé sur des algo "tous fais", donc l'optimiseur n'a qu'à vérifier que la requête contient certains patterns afin d'appliquer la bonne méthode, c'est assez rapide.
 
Ensuite par contre, la lecture des index, les tris, et surtout les regroupements ça bouffe énormément de temps, d'autant plus quand il y a des distinct : une première lecture pour faire un tri temporaire, puis une seconde lecture pour virer les doublons, c'est la mort pour le SGBD. Ensuite, pour la construction du curseur et la récupération des indexes, je pense que ça se passe d'explications, ça extrêment lent, à cause de limitations purement matérielles.


:jap:
Non, je parlais de la 2è étape que tu as décrite ("Ensuite, c'est l'éxécution de la requête" ).


Message édité par sircam le 21-09-2004 à 10:04:04

---------------
Now Playing: {SYNTAX ERROR AT LINE 1210}
Reply

Marsh Posté le 21-09-2004 à 11:01:42    

Ah ok :) Ben là ça dépends complètement de la requête et de la présence d'indexes ou non :)
Mais à partir du moment où il y a beaucoups de lignes à retourner, c'est dans tous les cas cette l'étape suivante la plus longue.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed