SQL Server 2005 et fonctions dans les requêtes

SQL Server 2005 et fonctions dans les requêtes - SQL/NoSQL - Programmation

Marsh Posté le 10-10-2007 à 16:02:00    

Hello
 
J'ai un tout petit problème qui me bloque depuis ce matin :'(
 
J'ai besoin du résultat d'une fonction dans une clause WHERE.
 
Lorsque je mets ma fonction dans le select, ça marche impec :

Code :
  1. SELECT pouet, FCTruc(machin) FROM bidule


 
Mais lorsque je mets ma fonction dans la clause WHERE, ça me fait un timeout :

Code :
  1. SELECT pouet FROM bidule WHERE FCTruc(machin) = 2


 
J'ai essayé de feinter en mettant un alias au résultat de ma fonction, et en testant sur cet alias, mais ça marche pas (ça serait trop beau)

Code :
  1. SELECT pouet, FCTruc(machin) AS m FROM bidule WHERE m = 2


 
du coup je comprend pas trop :'(
 
 
ma fonction :
 

Code :
  1. SET ANSI_NULLS ON
  2. GO
  3. SET QUOTED_IDENTIFIER ON
  4. GO
  5. ALTER FUNCTION [dbo].[FCClubJeu]
  6. (
  7.     @activite_id int
  8. )
  9. RETURNS int
  10. AS
  11. BEGIN
  12.     DECLARE @structure_id int
  13.  
  14.     -- si prêté : renvoi de la structure de prêt
  15.     SELECT @structure_id = structure_id
  16.         FROM ActiviteDansStructure
  17.         WHERE activite_id = @activite_id
  18.         AND activitedansstructure_pret = 1
  19.         OR activitedansstructure_mutation = 1
  20.     
  21.     IF NOT @structure_id IS NULL
  22.         RETURN @structure_id
  23.  
  24.     -- par défaut : structure sans prêt ni mutation
  25.     SELECT @structure_id = structure_id
  26.         FROM ActiviteDansStructure
  27.         WHERE activite_id = @activite_id
  28.         AND activitedansstructure_pret = 0
  29.         AND activitedansstructure_mutation = 0
  30.  
  31.     RETURN @structure_id
  32.  
  33. END


 
 
et voici ma requête :
 

Code :
  1. SELECT individu_id, individu_civilite, individu_nom, individu_prenom, individu_numlicence,
  2. individu_sexe, individu_datenaissance, typeprofil_code, structure_id, structure_nom,
  3. dbo.FCNumClub(structure_id) AS numclub, categorie_nom, activite_id, activite_valide, activite_dateexpedition,
  4. (SELECT TOP (1) activitedansstructure_id FROM ActiviteDansStructure
  5.     WHERE (activite_id = VInfosCompletes.activite_id) AND (activitedansstructure_pret = 1)) AS prete
  6. FROM VInfosCompletes
  7. WHERE (profil_joueur = 1)
  8. AND (structure_id = @club)
  9. AND (typeprofil_id = CASE WHEN @profil IS NULL THEN typeprofil_id ELSE @profil END)
  10. AND (categorie_id = CASE WHEN @cat IS NULL THEN categorie_id ELSE @cat END)
  11. AND (saison_active = 1)
  12. ORDER BY categorie_ordre, individu_nom


 
quelqu'un pour m'aider ? :'(


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 10-10-2007 à 16:02:00   

Reply

Marsh Posté le 10-10-2007 à 16:07:45    

first :o

Reply

Marsh Posté le 10-10-2007 à 16:11:38    

Reply

Marsh Posté le 10-10-2007 à 16:32:35    

deuz [:el g]


---------------
I'm failing as fast as I can !! -- Vision-360, vos photos en grand format -- !! -- Les nouilles c'est bon
Reply

Marsh Posté le 10-10-2007 à 16:35:29    

heureusement que vous êtes là [:cerveau dawa]


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 10-10-2007 à 17:34:02    

bon tout le monde s'en fout de mon problème qui me bloque complètement et qui arrive pile au moment de ma négociation de salaire ? [:opus dei]


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 10-10-2007 à 17:39:44    

Reply

Marsh Posté le 10-10-2007 à 17:43:04    

Très honnêtement, je ne vois pas pourquoi ça merde.
 
Question bête cependant... T'as combien de ligne dans ta table ?
 
En effet, la première ligne ne sera retournée que lorsque la clause WHERE sera entièrement vérifiée, ce qui implique l'exécution de ta fonction pour toute les lignes de la table avant de retourner la moindre ligne.
 
En revanche, la fonction dans le select n'est évaluée que lorsque les lignes commencent à arriver (à condition qu'aucun critère de tri ne pointe dessus évidement). Ainsi, tu as des lignes retournées dès qu'un nombre suffisant pour remplir la première page de buffer est traîtée. Sur un gros volume, on se rend bien compte que ça change du tout au tout.
 
Tu peux tester :
1/ Clause HAVING, qui permet de faire un critère sur le résultat d'une requête (à mon avis ça ne marchera pas mieux)
2/ Faire un select global qui filtre le résultat de la première requête. A mon avis, tu vas pas gagner grand chose, voir rien du tout.
 
Est-tu vraiment obligé de passer par la fonction ? Effectivement, c'est mieux de refactoriser, mais dans ton cas, une jointure pourrait s'avérer bien plus rapide.

Reply

Marsh Posté le 10-10-2007 à 18:01:21    


[:cerveau zytrasnif]
 

MagicBuzz a écrit :

Question bête cependant... T'as combien de ligne dans ta table ?


dans la vue VInfosCompletes, juste 17038 [:robert de niro]
 
 

MagicBuzz a écrit :

En effet, la première ligne ne sera retournée que lorsque la clause WHERE sera entièrement vérifiée, ce qui implique l'exécution de ta fonction pour toute les lignes de la table avant de retourner la moindre ligne.


effectivement, ça risque de poser quelques problèmes de lenteur :sweat:
 

MagicBuzz a écrit :

En revanche, la fonction dans le select n'est évaluée que lorsque les lignes commencent à arriver (à condition qu'aucun critère de tri ne pointe dessus évidement). Ainsi, tu as des lignes retournées dès qu'un nombre suffisant pour remplir la première page de buffer est traîtée. Sur un gros volume, on se rend bien compte que ça change du tout au tout.


okay [:romf]
 

MagicBuzz a écrit :

Tu peux tester :
1/ Clause HAVING, qui permet de faire un critère sur le résultat d'une requête (à mon avis ça ne marchera pas mieux)
2/ Faire un select global qui filtre le résultat de la première requête. A mon avis, tu vas pas gagner grand chose, voir rien du tout.


1/ http://msdn2.microsoft.com/en-us/library/ms180199.aspx

Citation :

When GROUP BY is not used, HAVING behaves like a WHERE clause


donc je doute que ça change quoi que ce soit :o (d'autant plus qu'avec ça, il veut à tout prix que je fasse un aggregate, sauf que j'ai pas du tout envie)
2/ je vois pas trop ce que tu veux dire
 

MagicBuzz a écrit :

Est-tu vraiment obligé de passer par la fonction ? Effectivement, c'est mieux de refactoriser, mais dans ton cas, une jointure pourrait s'avérer bien plus rapide.


non, je suis pas obligé, c'est juste la seule méthode que j'ai trouvé :o
avec une jointure, tu voudrais faire comment ?


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 10-10-2007 à 18:45:27    

perso je passerai par l'explain plan pour déja voir un peu,  
j'essayerai aussi sans l'order by car du coup il ne serait plus obligé d'avoir l'entiereté des records pour fetcher et au moins tu verrais peut-etre apparaitre qques records.
j'aurai aussi tendance a virer ceci pendant la phase de debug

Code :
  1. (SELECT TOP (1) activitedansstructure_id FROM ActiviteDansStructure   
  2. WHERE (activite_id = VInfosCompletes.activite_id) AND (activitedansstructure_pret = 1)) AS prete


 


Message édité par casimimir le 10-10-2007 à 18:46:44
Reply

Marsh Posté le 10-10-2007 à 18:45:27   

Reply

Marsh Posté le 11-10-2007 à 10:06:07    

explain plan ? wtf ?
 
l'order by c'est nécessaire malheureusement :/
et la sous-requête aussi :D


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 11-10-2007 à 10:16:09    

ben euuhhh le plan d'exécution, la manière dont le sgbd va construire ta requete, j'ai du jouer 2* avec du microsoft mais y a un tab avec ca tout fait dans le machin enterprise bidule non?
 
je sais bien que l'order by et la sous requete sont nécessaires, mais je les virerai pour voir ce qui impacte tes perfs et tu les remets après et peut-être pas tel quel

Reply

Marsh Posté le 11-10-2007 à 10:29:35    

Pour faire apparaître le tab il faut avant aller dans une option dans "affichage" ou un truc du genre.
 
Sinon, +1 pour le mode "pas à pas" :
 
"select 1"
=> F5.
 
Après on commence à discuter, à ajouter une table à la fois, et un champ à la fois, histoire de localiser exactement quel bout de la requête ralenti de façon significative.
Ca va bien plus vite comme ça.
 
En effet, en plus de la fonction, il se peut que ça merde ailleurs. Des fois le SQL c'est très chiant pour ça :D T'as un big bug. C'est bien, super rapide. Tu rajoutes un truc qui est bon, et proutch, ça ramme à donf. Tu t'escrimes à debug un truc juste, alors que ct avant que ça merdait ;)


Message édité par MagicBuzz le 11-10-2007 à 10:31:09
Reply

Marsh Posté le 11-10-2007 à 10:33:19    

okay, j'essayerais avec le plan d'exécution [:romf]


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 11-10-2007 à 10:35:48    

au fait, truc qui n'a rien à voir, mais c'est pour la beauté de l'art :
 

Code :
  1. CASE WHEN @profil IS NULL THEN typeprofil_id ELSE @profil END


 
C'est plus joli comme ça :

Code :
  1. isnull(@profil, typeprofil_id)

Reply

Marsh Posté le 11-10-2007 à 10:50:23    

ah oui pas con :D (je connaissais pas isnull mais je connais coalesce, qui fait pareil)


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Marsh Posté le 11-10-2007 à 10:54:43    

bon, j'ai fait ça complètement différemment, et ça marche :D
(j'ai mis la fonction dans le select, et à l'affichage, je test si la structure de prêt est la même que la structure de jeu)
merci pour votre aide, les tips m'aideront quand-même pour la suite [:romf]


---------------
Android/Manettes/Metroidvania/Zelda/Indés/Retrogaming/VDS jeux
Reply

Sujets relatifs:

Leave a Replay

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