8
votes

Réduction de la redondance / duplication en code SQL

dans Cette question sur Stackoverflow, la réponse acceptée implique de répéter les mêmes extraits de code plusieurs fois. De mon expérience, de nombreuses personnes s'efforcent de réduire cela en encapsulant les extraits de code de différentes manières, pour diverses raisons;
- la maintenabilité (moins de lieux de changement)
- Lisibilité (lisez le code une fois, alors c'est «alias» à chaque heure ultérieure)
- etc, etc

Utiliser le code dans la question liée, comment définiriez-vous pour réduire la répétition des extraits de code identiques? Ou voudriez-vous simplement le laisser comme-est? P>

(n'utilisant pas une logique alternative, mais collez-vous à l'utilisation de remplacer, etc., changeez simplement la présentation de la même logique.) P>

Select  Case
        When CharIndex('.', Replace(URL, 'www.','')) > 0 then
           Left(Replace(URL, 'www.',''), CharIndex('.',Replace(URL, 'www.',''))-1)
        Else
           Replace(URL, 'www.','')
        End as [CleanURL]
From dbo.YourTable 


6 commentaires

Vous pouvez créer une fonction SQL pour faire le nettoyage.


Dans cette fonction, la duplication du code existe toujours. Ainsi, pour écrire cette logique, dans n'importe quel contexte, le code contient duplication. (Remplacer est utilisé à l'identique 4 fois, par exemple.)


Ahhhhh, je vois maintenant ce que tu veux dire. Eh bien, je pense que c'est assez lisible si vous l'utilisez dans une seule fonction et hautement maintenable. La mise en place de structures SQL plus difficiles à lire n'est pas agréable pour les autres programmeurs ayant à maintenir votre code (si leurs compétences ne sont pas aussi élevées que la vôtre)


Cet exemple particulier est assez simple, je suis d'accord. Je rencontre souvent le même problème sur des formes plus compliquées, mais je pensais que c'était un bon exemple simplifié pour établir le principe.


Vous l'utiliseriez dans une fonction, peut-être utiliser si plutôt que par un cas instruction et utilisez une variable pour stocker le résultat du remplacer si Vous en avez besoin sur tous les chemins de code.


@chris - qui ne traite pas (en soi) qui ne répond pas aux utilisations dupliquées de remplacer dans la fonction résultante. Cela ne consiste pas à encapsuler ce morceau de code, mais de réduire la redondance dans cette pièce de code.


6 Réponses :


0
votes
WITH
  prefix_removed
AS
(
  SELECT
    *,
    REPLACE(URL, 'www.','') AS myURL_NoPrefix
  FROM
    myTable
)
,
  suffix_start
AS
(
   SELECT
     *,
     CharIndex('.', myURL_NoPrefix) AS domain_end
   FROM
     prefix_removed
)
SELECT
  CASE WHEN
    doamin_end = 0
  THEN
    myURL_NoPrefix
  ELSE
    LEFT(myURL_NoPrefix, domain_end-1)
  END AS domain
FROM
  prefix_removed

4 commentaires

Votre solution semble permettre la possibilité d'adresses telles que www.nosuffixdomain , mais ne fait rien des adresses telles que noprefixdomain-www.com . Lequel des deux pensez-vous est plus susceptible de rencontrer?


Je suis vraiment impressionné par la manière dont vous n'avez pas complètement compris que la logique elle-même n'est pas pertinente. Question, commentaires, modifications, tous totalement ignorés. Il ne s'agit pas de la logique, la logique est un cas d'échantillon, dont le comportement exact est totalement non pertinent.


Je suis désolé. Ne dirais pas que tout a été ignoré, cependant, encore des morceaux cruciaux étaient probablement. Encore pardon.


@Andriym - Necro Post - Il semble que j'étais un #### er à l'époque, je m'excuse tardivement!



0
votes

Le avec la clause code> devrait être Très approprié pour cela:

WITH replaced_urls AS (
    SELECT Replace(URL, 'www.','') AS url,
           CharIndex('.', Replace(URL, 'www.','')) AS idx
    FROM dbo.YourTable
)
Select  Case
    When idx > 0 then
       Left(url, idx-1)
    Else
       url
    End as [CleanURL]
From replaced_urls 


1 commentaires

J'ai édité mes explications dans la réponse de Mikael Eriksson, qui est meilleure que la mienne. Je vais supprimer cela une fois que la modification est acceptée.



0
votes

Ceci est un exemple avec une fonction xxx

la fonction qui prend soin du formatage xxx

Vous pouvez alors appeler cette fonction de chaque requête.


2 commentaires

Toutes mes excuses, je voulais dire autre chose. Je ne veux pas dire "Comment éviter de rédiger cette logique plusieurs fois", mais "Comment éviter de répéter dans cette pièce de code". Éviter l'utilisation dupliquée de remplacer, par exemple, comme il est identique dans les 4 places.


J'ai édité mon post. Cela peut être fait assez facilement. De cette façon, vous n'avez que le remplacement une fois et stockez-le dans un var. Je ne pense pas que c'est le meilleur performant. Mais c'est lisible et maintenu.



0
votes
SELECT
  myTable.*,
  LEFT(noPrefix.myURL, domain_end.pos) AS domain
FROM
  myTable
CROSS APPLY
  (SELECT REPLACE(myTable.myURL, 'www.', '') AS myURL) AS [noPrefix]
CROSS APPLY
  (SELECT CHARINDEX('.', noPrefix.MyURL) AS pos) AS [suffix_start]
CROSS APPLY
  (SELECT CASE WHEN suffix_start.pos = 0 THEN LEN(noPrefix.myURL) ELSE suffix_start.pos - 1 END AS pos) AS [domain_end]

0 commentaires

1
votes

Inspiré par UW Concept, mais à l'aide d'une fonction de table et de sub_Quisery pour éviter les pénalités de performance associées à la fonction Stralar Stralar et à l'utilisation d'une variable interne. xxx

à l'aide de la fonction suivante. .. xxx


7 commentaires

Cela ressemble à une solution soignée. Même si je ne connais pas le coût de performance d'un sous-sélection trois niveaux. Je suppose que c'est plus rapide que d'attribuer des valeurs à une variable?


Le moteur d'optimisation doit pouvoir le désactiver extrêmement efficacement, comme s'il n'y avait pas de sous-sélection. Il devrait se comporter de la même manière que l'utilisation d'une vue, étant étendue en ligne dans toute requête qui utilise la fonction, puis compilée de manière assez efficace.


Je ne comprends pas comment vous pouvez dire qui fonctionnera mieux sans tester? Votre fonction de valorisation de la table contient des erreurs de syntaxe, il n'y a pas d'instruction retour ou Tableau defintion


Je ne peux pas indiquer catégoriquement une différence de performance. Mais je peux être sûr de certains mécanismes en jeu. Le facteur prédominant que j'avais à l'esprit est que la fonction de valorisation de la table peut être définie comme une "inline", qui est sans aucun DDL, T-SQL, etc., juste une requête droite. Une conceptualisation de ceci est que l'optimiseur peut efficacement «copier et coller» ce code dans n'importe quelle requête qui utilise la fonction, et la compilez à partir de là. Aussi opé à l'utilisation d'une fonction scalaire intrinsèquement non définie basée et non optimible de la même manière.


retour instruction ajoutée. Définition de la table non requise.


Utiliser avec est plus lisible et concis, tout en obtenant la même chose. Regardez l'exemple de la réponse de Mikael Eriksson.


@DANCEK: Votez pour cela alors :) J'essaie effectivement d'essayer (et d'échouer) d'obtenir un sondage de paille d'opinions et d'options.



6
votes
select
  case
    when c2.idx > 0 then
      left(c1.url, c2.idx)
    else
      c1.url
  end
from myTable as m
  cross apply (select replace(m.URL, 'www.', '')) as c1(url)
  cross apply (select charindex('.', c1.url)) as c2(idx)

3 commentaires

Concaténation '.' à la ficelle est un bon tour. C'est un peu moins lisible, bien que ...


En fait, je voulais dire que c'est plus lisible mais aussi plus difficile à comprendre.


Je conviens que c'est un bon tour pour le code concis, mais cela fait du genre de jupe autour du point de ma question. J'avais espéré faire un sondage en paille de la réduction de la répétition dans le code et non de refactoriser la logique elle-même, la logique choisie est un cas d'échantillon, et non une question elle-même. En tant que tel, l'utilisation du CTE pour le remplacement est pertinente pour ma question, l'utilisation du + '.' casse la "même logique" contrainte :( je suis tenté de supprimer cette question comme Il semble que ce soit le point soit complètement manqué :(