2013-06-10 2 views
0

J'ai essayé de trouver les ventes totales mensuelles, les valeurs totales de renvoi pour chaque client pendant 12 mois.UDF vs sous-question de performance de la question

Avec 2 autres sous-requêtes, la requête devient 26 sous-requête pour chaque ligne et la phrase sql est très grande.

alors je créer deux subselect à vendre et les totaux sendback ...

La requête de résultat est devenu plus court, mais le temps d'exécution est plus grande que 20-30 fois.

  1. Est-ce normal
  2. Comment puis-je retourner 0 si le subqery retourne NULL ..

EDIT:

(Select sum(chh2.cha_meblag) 
from dbo.CARI_HESAP_HAREKETLERI chh2 
where chh2.cha_normal_Iade=1 and 
     chh2.cha_kod=ch.cari_kod and 
     (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131') 
) as Ocai 
+2

Des questions comme celles-ci sont impossible de répondre intelligemment sans voir le code. Pour votre première question, cependant, cela ne me surprend pas qu'une requête avec un UDF soit plus lente qu'une requête équivalente sans un. –

+0

Je pense à poster du code pour 1. mais j'ai vu une question comme celle-ci lorsque googlé et je veux juste obtenir une réponse simple. pour le second. (Sélectionnez la somme (chh2.cha_meblag) de dbo.CARI_HESAP_HAREKETLERI chh2 où chh2.cha_normal_Iade = 1 et chh2.cha_kod = ch.cari_kod et (chh2.cha_tarihi> = '20130101' et chh2.cha_tarihi <= '20130131')) as Ocai, Comment définir cette requête pour renvoyer 0 lorsque null. – ikutluay

Répondre

1

La réponse à votre deuxième question est d'envelopper la sous-requête dans un coalesce():

coalesce((Select sum(chh2.cha_meblag) 
      from dbo.CARI_HESAP_HAREKETLERI chh2 
      where chh2.cha_normal_Iade=1 and 
       chh2.cha_kod=ch.cari_kod and 
       (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131') 
     ), '') as Ocai 

Comme le souligne Martin dans son commentaire, coalesce() a ce que je considère comme un bogue dans SQL Server. Dans ce cas, il exécutera deux fois la première expression, une fois pour vérifier la valeur par rapport à NULL et la seconde fois pour obtenir la valeur. Compte tenu de cela, ISNULL() est mieux (même si je préfère les fonctions standard en général):

isnull((Select sum(chh2.cha_meblag) 
      from dbo.CARI_HESAP_HAREKETLERI chh2 
      where chh2.cha_normal_Iade=1 and 
       chh2.cha_kod=ch.cari_kod and 
       (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131') 
     ), '') as Ocai 
+1

['ISNULL is better'] (http://connect.microsoft.com/SQLServer/feedback/details/336002/unnecessarily-bad-performance-for-coalesce-subquery) –

+0

@MartinSmith. . . Merci de me rappeler de cette lacune dans SQL Server. Y a-t-il des plans pour le réparer? –

1

En fonction de votre sous-requête il semble que vous pouvez résoudre votre problème sans sous-requêtes corrélative et seulement en utilisant des jointures. Cependant, avec seulement une partie d'une requête à travailler avec elle est difficile d'être sûr. C'est pourquoi, lorsque vous postez des questions, il est judicieux d'afficher autant de code que possible. Néanmoins, d'après ce que je vous rassemblerai avez somthing comme ceci:

SELECT ( SELECT SUM(chh2.cha_meblag) 
      FROM dbo.CARI_HESAP_HAREKETLERI chh2 
      WHERE chh2.cha_normal_Iade = 1 
      AND  chh2.cha_kod = ch.cari_kod 
      AND  chh2.cha_tarihi >= '20130101' 
      AND  chh2.cha_tarihi <= '20130131' 
     ) AS Ocai, 
     ( SELECT SUM(chh2.cha_meblag) 
      FROM dbo.CARI_HESAP_HAREKETLERI chh2 
      WHERE chh2.cha_normal_Iade = 1 
      AND  chh2.cha_kod = ch.cari_kod 
      AND  chh2.cha_tarihi >= '20130201' 
      AND  chh2.cha_tarihi <= '20130228' 
     ) AS Ocai, 
     ... etc for 12 months 
FROM SomeTable ch 

Vous pouvez transformer cela en:

SELECT ch.cari_kod, 
     [20130101] = ISNULL([20130101], 0), 
     [20130201] = ISNULL([20130201], 0), 
     [20130301] = ISNULL([20130301], 0), 
     [20130401] = ISNULL([20130401], 0), 
     [20130501] = ISNULL([20130501], 0), 
     [20130601] = ISNULL([20130601], 0), 
     [20130701] = ISNULL([20130701], 0), 
     [20130801] = ISNULL([20130801], 0), 
     [20130901] = ISNULL([20130901], 0), 
     [20131001] = ISNULL([20131001], 0), 
     [20131101] = ISNULL([20131101], 0), 
     [20131201] = ISNULL([20131201], 0) 
FROM SomeTable 
     LEFT JOIN 
     ( SELECT chh2.cha_kod, 
        [20130101] = SUM(CASE WHEN chh2.cha_tarihi >= '20130101' AND chh2.cha_tarihi < '20130201' THEN chh2.cha_meblag ELSE 0 END), 
        [20130201] = SUM(CASE WHEN chh2.cha_tarihi >= '20130201' AND chh2.cha_tarihi < '20130301' THEN chh2.cha_meblag ELSE 0 END), 
        [20130301] = SUM(CASE WHEN chh2.cha_tarihi >= '20130301' AND chh2.cha_tarihi < '20130401' THEN chh2.cha_meblag ELSE 0 END), 
        [20130401] = SUM(CASE WHEN chh2.cha_tarihi >= '20130401' AND chh2.cha_tarihi < '20130501' THEN chh2.cha_meblag ELSE 0 END), 
        [20130501] = SUM(CASE WHEN chh2.cha_tarihi >= '20130501' AND chh2.cha_tarihi < '20130601' THEN chh2.cha_meblag ELSE 0 END), 
        [20130601] = SUM(CASE WHEN chh2.cha_tarihi >= '20130601' AND chh2.cha_tarihi < '20130701' THEN chh2.cha_meblag ELSE 0 END), 
        [20130701] = SUM(CASE WHEN chh2.cha_tarihi >= '20130701' AND chh2.cha_tarihi < '20130801' THEN chh2.cha_meblag ELSE 0 END), 
        [20130801] = SUM(CASE WHEN chh2.cha_tarihi >= '20130801' AND chh2.cha_tarihi < '20130901' THEN chh2.cha_meblag ELSE 0 END), 
        [20130901] = SUM(CASE WHEN chh2.cha_tarihi >= '20130901' AND chh2.cha_tarihi < '20131001' THEN chh2.cha_meblag ELSE 0 END), 
        [20131001] = SUM(CASE WHEN chh2.cha_tarihi >= '20131001' AND chh2.cha_tarihi < '20131101' THEN chh2.cha_meblag ELSE 0 END), 
        [20131101] = SUM(CASE WHEN chh2.cha_tarihi >= '20131101' AND chh2.cha_tarihi < '20131201' THEN chh2.cha_meblag ELSE 0 END), 
        [20131201] = SUM(CASE WHEN chh2.cha_tarihi >= '20131201' AND chh2.cha_tarihi < '20140101' THEN chh2.cha_meblag ELSE 0 END) 
      FROM dbo.CARI_HESAP_HAREKETLERI chh2 
      WHERE chh2.cha_normal_Iade = 1 
      GROUP BY chh2.cha_kod 
     ) chh2 
      ON chh2.cha_kod = ch.cari_kod; 

Cela peut même pas besoin d'un sous-requête, mais comme je l'ai dit, sans votre requête complète Je ne peux que spéculer sur la structure de votre table et les résultats que vous voulez réellement.

Pour répondre à 1 oui, il est normal qu'un fichier UDF fonctionne moins bien qu'une sous-requête faisant la même chose. Il y a un certain nombre de messages sur le sujet This answer était au sommet de google quand j'ai cherché SQL-Server UDF versus subquery

+0

Merci à tous les gars .. Vos conseils sont excellents .. – ikutluay