Évitez de répéter le fragment SQL dans la requête?

J'ai cette requête (pseudo code)

SELECT a = 1, b = 2, c = CASE WHEN ISNULL( (SELECT MONTH(GETDATE()) <---long query ), 0) = 0 THEN 'found' ELSE SELECT MONTH(GETDATE()) <--- repeated long query END 

Le problème est que le SELECT MONTH(GETDATE()) qui en réalité est très longue requête.

Existe-t-il une solution de contournement pour cette "expression longue" pour ne pas apparaître deux fois dans la requête?

ps

J'ai une solution de calculer SELECT MONTH(GETDATE()) dans une variable externe … mais j'essaye de comprendre s'il y a une solution en ligne.

Le model particulier d'utilisation d'une sous-requête dans votre exemple pourrait être réécrit comme ceci:

 … c = COALESCE(CAST(NULLIF(( subquery ), 0) AS varchar(10)), 'found') … 

Comme Mikael Eriksson l'a correctement souligné dans son commentaire, vous devrez peut-être utiliser ISNULL au lieu de COALESCE ici, car l'un des arguments contient une sous-requête et ISNULL peut (ou, en fait, sera) plus efficace dans ce cas, peut voir élaboré dans cette réponse .

alors voici le ver fixe:

 … c = ISNULL(CAST(NULLIF(( subquery ), 0) AS varchar(10)), 'found') … 

Notez, cependant, que si vous ISNULL par passer à ISNULL , vous devriez faire attention à la longueur de la deuxième string ( 'found' ) si vous décidez de la changer aussi. Le fait est que ISNULL va tenter de ISNULL le second argument en le type exact du premier argument, y compris la longueur maximale de la string spécifiée ( 10 dans ce cas). Si votre deuxième argument devient quelque chose comme 'NULL or zero is found' au lieu de simplement 'found' , ISNULL ne returnnera pas la string entière mais seulement les 10 premiers caractères à la place ( 'NULL or ze' ). Vous devrez donc vous callbacker de changer le type du premier argument (par exemple varchar(20) ).

Vous avez un certain nombre d'options disponibles:

  • Fonction définie par l'user (UDF)
  • Vues
  • Expression de table commune (CTE)
  • CROSS / APPLICATION EXTÉRIEURE

Selon la manière dont datatables sont traitées, vous déterminerez quel est le meilleur ajustement. Votre question ne fournit pas assez de détails pour offrir une suggestion définitive, mais celles-ci méritent d'être examinées.

Veillez à utiliser UDF car ils peuvent rapidement entraver les performances. Mon sharepoint vue personnel est d'écrire un file UDF pour des transformations de données simples ou un calcul mathématique. J'essaie d'éviter de faire des opérations complexes basées sur des sets dans une fonction et je préférerai une vue ou un CTE pour cela.

 SELECT a = 1, b = 2, c = CASE WHEN ISNULL([l], 0) = 0 THEN 'found' ELSE [l] END from tbl cross apply ( SELECT MONTH(GETDATE()) as [l] ) as [x] 

En outre, si votre requête d'origine est représentative de ce que vous avez réellement obtenu (c.-à-d. COALESCE une valeur si l'expression longue renvoie null), envisagez d'utiliser COALESCE au lieu d'une instruction case. Ou utilisez simplement ISNULL([l], 'found')

Exemple utilisant CTE

 ;WITH CTE AS ( SELECT CASE WHEN ISNULL(MONTH(GETDATE()),0) = 0 THEN 'FOUND' ELSE ISNULL(MONTH(GETDATE()),0) END Col1 ), SELECT a = 1,b = 2, C = col1 FROM Table1, CTE 

si vous avez des keys, cela peut être utilisé pour join

 SELECT a = 1,b = 2, C = CASE WHEN ISNULL(v.col1,0) = 0 THEN 'Found' ELSE v.col1 END FROM Table1 a OUTER APPLY (SELECT ISNULL(MONTH(DateCol),0) Col1 FROM TABLEName b a.id = b.id) v