IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Utilisation de variables pour optimiser une vue


Sujet :

Développement SQL Server

  1. #1
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut Utilisation de variables pour optimiser une vue
    Bonjour

    J'ai écrit cette requête en passant par des variable pour éviter de faire des CAST(datetime as date) et des calcul sur GetDate() dans l’exécution

    Et j'aurais voulu en faire une vue
    Mais je constate hélas qu'il n'est pas possible de déclarer des Variables dans une vue

    Existe-t-il une autre manière ?

    Merci de votre aide



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    DECLARE @Today AS Datetime
    DECLARE @MONBEG AS Datetime
    DECLARE @YEARBEG AS Datetime
    SET @Today=CAST(GETDATE() AS DATE)
    SET @MONBEG=DATEADD(month, DATEDIFF(month, 0, @Today), 0)
    SET @YEARBEG=DATEADD(yy, DATEDIFF(yy, 0, @Today), 0)
     
    SELECT
     
    dbo.TradeInBaskets.AffiliateId,
    SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN @YearBeg AND @MonBeg THEN 1 else 0 END) AS YTMBeg ,
    SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN @MONBEG AND @Today THEN 1 else 0 END) AS MTYest ,
    SUM(CASE WHEN TradeInBaskets.DateTime >@Today THEN 1 else 0 END) AS Today ,
    SUM(CASE WHEN TradeInBaskets.IsCancelled=1 THEN 1 ELSE 0 END ) AS NbCancel,
    SUM(CASE WHEN TradeInBaskets.IsCancelled=0 THEN TradeInBaskets.TradeInPrice ELSE 0 END) AS Value
     
    from TradeInBaskets
    WHERE DateTime>@YEARBEG
    GROUP by Affiliateid

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 138
    Par défaut
    Et qu'est-ce qui t’empêche de mettre tes expressions de date dans la requête ?
    C'est peut-être un peu lourd à la relecture mais elles ne seront calculées qu'une fois lors de l'exécution.
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  3. #3
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,

    En effet, une vue ne doit contenir qu'une requête et rien d'autre.
    Vous pourriez passer par une fonction table multi-instruction, mais vous risquez de perdre beaucoup en performances.

    Concernant le fait de mettre vos calculs directement dans la requête, au niveau de performances, les calculs ne seront pas faits pour chaque ligne, mais bien une seule fois pour la requete.
    Si c'est pour un problème de lisibilité/maintenance, vous pouvez passer par par une CTE (ou sous requete) pour factoriser le code.

    Quelque chose comme ceci par exemple (pas testé)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    WITH CTE(Today, monbeg, yearbeg) AS ( 
    	SELECT 
    			CAST(GETDATE() AS DATE)
    		,	DATEADD(month, DATEDIFF(month, 0, @Today), 0)
    		,	DATEADD(yy, DATEDIFF(yy, 0, @Today), 0)
    )
    SELECT  
    	dbo.TradeInBaskets.AffiliateId,
    	SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN YearBeg AND MonBeg THEN 1 else 0 END) AS YTMBeg ,
    	SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN MONBEG AND Today THEN 1 else 0 END) AS MTYest ,
    	SUM(CASE WHEN TradeInBaskets.DateTime >Today THEN 1 else 0 END) AS Today ,
    	SUM(CASE WHEN TradeInBaskets.IsCancelled=1 THEN 1 ELSE 0 END ) AS NbCancel,
    	SUM(CASE WHEN TradeInBaskets.IsCancelled=0 THEN TradeInBaskets.TradeInPrice ELSE 0 END) AS Value
     
    from TradeInBaskets
    CROSS JOIN CTE 
    WHERE DateTime>YEARBEG
    GROUP by Affiliateid

  4. #4
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    excellent !

    Merci Aieeeuuuuu

    J'avais oublié que c'était possible !

  5. #5
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 009
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par aieeeuuuuu Voir le message
    Bonjour,

    En effet, une vue ne doit contenir qu'une requête et rien d'autre.
    Vous pourriez passer par une fonction table multi-instruction, mais vous risquez de perdre beaucoup en performances.
    Il peut dans ce cas faire une fonction table en ligne et conserver toutes les performances... Mais je n'en voit pas l'intérêt...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  6. #6
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Pour ma part la Solution proposé par Aieeeuuu permet

    - une bien meilleure lisibilité (ce qui aide beaucoup la compréhension et la maintenance
    - Cela évite les erreurs liée a une syntaxe trop encombrée
    - Et A mon avis cela n'affecte pas la performance

  7. #7
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Bonjour

    J'ai aménagé la solution d'Aieeeuuuu qui ne fonctionne pas tel que (il avait averti ne pas avoir testé)

    Il y avait deux soucis :
    - Le CTE n'autorise pas la reference directe a @Today calculé dans l'expression
    - Il n'est pas possible d'utiliser les élément de CTE sans faire référence a celle ci (j'ai résolu en faisant un JOIN virtuel)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    WITH CTE(Today, monbeg, yearbeg) AS ( 
    	SELECT TOP 1
    			CAST(GETDATE() AS DATE) AS Today
    		,	DATEADD(month, DATEDIFF(month, 0, CAST(GETDATE() AS DATE)), 0) AS MonBeg
    		,	DATEADD(yy, DATEDIFF(yy, 0, CAST(GETDATE() AS DATE)), 0) AS YearBeg
    )
    SELECT
    dbo.TradeInBaskets.AffiliateId,
    SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN CTE.YearBeg AND CTE.MonBeg THEN 1 else 0 END) AS YTMBeg ,
    SUM(CASE WHEN TradeInBaskets.DateTime BETWEEN CTE.MONBEG AND Today THEN 1 else 0 END) AS MTYest ,
    SUM(CASE WHEN TradeInBaskets.DateTime >CTE.Today THEN 1 else 0 END) AS Today ,
    SUM(CASE WHEN TradeInBaskets.IsCancelled=1 THEN 1 ELSE 0 END ) AS NbCancel,
    SUM(CASE WHEN TradeInBaskets.IsCancelled=0 THEN TradeInBaskets.TradeInPrice ELSE 0 END) AS Value
     
    from TradeInBaskets
    INNER JOIN CTE ON CTE.monbeg=CTE.monbeg
    WHERE DateTime>YEARBEG
    GROUP by Affiliateid

  8. #8
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par olibara Voir le message
    Bonjour
    Quelle est la raison du "TOP 1" qui se trouve dans la CTE ?

    En effet, la CTE ne peut pas avoir plus d'une ligne, et mise à part si avoir explicitement un TOP 1 déclenche quelque changement dans le plan d'exécution (ce dont je toute un peu), il ne sert à rien.

    Quand à votre "join virtuel", votre syntaxe est une hérésie, illisible, et potentiellement non pérenne.

    "INNER JOIN" permet de lier une table à l'ensemble des tables déjà présentes dans la requête. Avec certains SGBD, le INNER JOIN serait rejeté, puisqu'il ne joint CTE à aucune autre table, et qui plus est, il compare deux champs d'une même table, ce qui est un filtre (certains SGBD tels qu'Access ne le supportent pas dans un JOIN). Donc sauf filtre sémantiquement important (du genre "type_personne = 'client'), un tel test ne doit se trouver que dans la clause WHERE.

    Comme dans l'exemple d'aieeeuuuuu, utilisez donc CROSS JOIN pour ajouter une table à votre requête sans jointure. Il se produit alors un produit cartésien, ce que votre INNER JOIN foireux fini par faire faute de faire une jointure.

  9. #9
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Merci Stringbuilder

    Tu a raison

    1- Le TOP c'est' juste une habitude d'écriture quand je sais que je ne m'attends qu'a une ligne
    2- De fait je n'avais pas vu le CROSS JOIN de Aieeeuuuu et comme effectivement sans JOIN ca ne peut pas marcher, j'ai inventé ce INNER JOIN Virtuel (Mais je prends note de la remarque)

  10. #10
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 009
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par olibara Voir le message
    1- Le TOP c'est' juste une habitude d'écriture quand je sais que je ne m'attends qu'a une ligne
    hou quelle vilaine habitude !!!

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 10
    Dernier message: 09/07/2017, 18h06
  2. utiliser une variable pour insérer une ligne
    Par goupil9 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 20/05/2012, 21h18
  3. Réponses: 4
    Dernier message: 11/01/2011, 15h58
  4. Réponses: 1
    Dernier message: 27/11/2008, 11h55
  5. Utiliser une variable pour désigner une colonne
    Par NicolasDeVos dans le forum SQL
    Réponses: 2
    Dernier message: 12/06/2008, 10h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo