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 :

Valeurs conditionnées sur date [2000]


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets MOE/MOA
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut Valeurs conditionnées sur date
    Bonjour,

    Dans le cadre de l'intégration du futur taux de TVA à 20% qui n'est pas sociale, nous allons mettre en place une structure TAXES du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE TAXES (
    	CI_ID INT IDENTITY (1, 1) NOT NULL ,
    	CC_TAXE CHAR(2) NOT NULL ,
    	CI_CODE SMALLINT NOT NULL ,
    	DD_VALEUR NOT NULL ,
    	QF_TAUX FLOAT NOT NULL ,
    	CONSTRAINT PK_TAXES PRIMARY KEY	(CI_ID)
    )
    Ainsi, un type de taxe (TVA, Eco-participation, TPHBJO, etc.) pourra prendre différentes valeurs en fonction d'un code numérique et d'une date (par exemple le taux spécifique pour la restauration passée de 19.6 à 5.5 puis à 7 en est un bon exemple. DD_VALEUR correspond à la date à partir de laquelle le taux est applicable.

    Cette table contiendra différentes valeurs du type :
    CC_TAXE = 'TVA'
    CI_CODE = 1
    DD_VALEUR = '1989-01-01'
    QF_TAUX = 20.6

    CC_TAXE = 'TVA'
    CI_CODE = 1
    DD_VALEUR = '2000-04-01'
    QF_TAUX = 19.6

    CC_TAXE = 'TVA'
    CI_CODE = 1
    DD_VALEUR = '2014-01-01'
    QF_TAUX = 20.0

    Dans ma table ARTICLES, j'ai un champ CI_TVA qui contient le code numérique relatif à la TVA applicable sur ledit article.

    Je souhaiterais à tout moment pouvoir faire une requète qui me retourne pour un article donné le taux de TVA applicable.

    Pour le moment nous employons une fonction :
    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
    20
    21
    CREATE FUNCTION fn_taux_date
    (
    	@cc_taxe	CHAR(3),
    	@ci_code	SMALLINT,
    	@dd_date	SMALLDATETIME
    )  
    RETURNS FLOAT AS
    BEGIN
    	DECLARE	@qf_retour	FLOAT
     
    	SELECT	@qf_retour = QF_TAUX
    	FROM	dba.TAXES t1 (NOLOCK)
    	WHERE	DD_VALEUR =
    		(SELECT	MAX(DD_VALEUR)
    		FROM	dba.TAXES t2 (NOLOCK)
    		WHERE	DD_VALEUR <= @dd_date
    			AND t2.CC_TAXE = t1.CC_TAXE AND t2.CI_CODE = t1.CI_CODE)
    		AND CC_TAXE = @cc_taxe AND CI_CODE = @ci_code
     
    	RETURN	ISNULL(@qf_retour, 0)
    END
    Et nous employons donc des requêtes du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT CHP1, CHP2, fn_taux_date('TVA', CI_TVA, @dd_date) FROM ARTICLES WHERE (...)
    Un des derniers papiers de maître Brouard m'a enseigné que l'utilisation des fonctions de cet acabit étaient à proscrire, y aurait-il un autre moyen ?

  2. #2
    Membre Expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Par défaut
    EN effet, dans votre cas créer une fonction de table incluse c'est à dire une fonction qui pour tout les code taxe et une date donnée vous retourne l'ENSEMBLE des taxes en vigueur à cette date.

    il ne vous reste plus qu'à faire un OUTER APPLY, ainsi votre fonction n'est appelée qu'une fois.

    Ou plus directement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT CHP1, CHP2,TAX.QF_TAUX
    FROM ARTICLES A
        OUTER APPLY
            (SELECT	 QF_TAUX
    	 FROM	dba.TAXES t1 (NOLOCK)
    	 WHERE	t1.CC_TAXE='TVA' AND t1.CC_CODE=A.CI_TVA
                           AND DD_VALEUR =
    		  (SELECT	MAX(DD_VALEUR)
    		    FROM	dba.TAXES t2 (NOLOCK)
    		    WHERE	DD_VALEUR <= @dd_date
    			    AND t2.CC_TAXE = t1.CC_TAXE AND t2.CI_CODE=t1.CI_CODE)) TAX

  3. #3
    Membre averti
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets MOE/MOA
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut
    Citation Envoyé par iberserk Voir le message
    EN effet, dans votre cas créer une fonction de table incluse c'est à dire une fonction qui pour tout les code taxe et une date donnée vous retourne l'ENSEMBLE des taxes en vigueur à cette date.

    il ne vous reste plus qu'à faire un OUTER APPLY, ainsi votre fonction n'est appelée qu'une fois.

    Ou plus directement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT CHP1, CHP2,TAX.QF_TAUX
    FROM ARTICLES A
        OUTER APPLY
            (SELECT	 QF_TAUX
    	 FROM	dba.TAXES t1 (NOLOCK)
    	 WHERE	t1.CC_TAXE='TVA' AND t1.CC_CODE=A.CI_TVA
                           AND DD_VALEUR =
    		  (SELECT	MAX(DD_VALEUR)
    		    FROM	dba.TAXES t2 (NOLOCK)
    		    WHERE	DD_VALEUR <= @dd_date
    			    AND t2.CC_TAXE = t1.CC_TAXE AND t2.CI_CODE=t1.CI_CODE)) TAX
    OUTER APPLY est-il applicable à SQL Server 2000 (la version que nous utilisons) ? Il me semble que non ?

  4. #4
    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,

    Non, en effet, OUTER APPLY n'est pas disponible sous 2000, comme plein d'autres fonctionnalités qui vous aurait été bien utiles. N'avez-vous pas prévu une mise à jour prochainement. Vous y gagnerez en performance, surtout pour ce type de requêtes...

    En attendant, vous pouvez tester ceci :

    Créer une vue qui indique le taux par plage de dates pour chaque type de taxes :
    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
    20
    21
     
    CREATE VIEW V_TAXES_APPLICABLES AS
    SELECT 
    		TDebut.CC_TAXE
    	,	TDebut.CI_CODE
    	,	TDebut.DD_VALEUR AS DateDebut
    	,	TFin.DD_VALEUR AS DateFin
    	,	TDebut.QF_TAUX
    FROM	TAXES TDebut
    LEFT JOIN TAXES TFin
    	ON		TFin.CC_TAXE = TDebut.CC_TAXE
    	AND		TFin.CI_CODE = TDebut.CI_CODE
    	AND		TFin.DD_VALEUR > TDebut.DD_VALEUR
    	AND		NOT EXISTS(
    				SELECT 1
    				FROM	TAXES T
    				WHERE	T.CC_TAXE = TFin.CC_TAXE
    				AND		T.CI_CODE = TFin.CI_CODE
    				AND		T.DD_VALEUR < TFin.DD_VALEUR
    				AND		T.DD_VALEUR > TDebut.DD_VALEUR
    			)
    Et dans vos requêtes, vous faites une jointure sur cette vue :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT A.* ,V.QF_TAUX
    FROM ARTICLES A
    INNER JOIN V_TAXES_APPLICABLES V
      ON V.CC_TAXE = A.CC_TAXE
      AND V.CI_CODE = A.CI_CODE
      AND V.DateDebut <= @dd_date
      AND (V.DateFin > @dd_date OR V.DateFin IS NULL)

  5. #5
    Membre averti
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets MOE/MOA
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut
    En appliquant cette solution sur une procédure spécifique, le plan d'exécution me donne les résultats suivants :
    requete avec les fonctions : 30.87 %
    requete avec les vues : 69.13 %

    Et dans le cas où une taxe n'est pas applicable sur un article, il faudrait un LEFT OUTER JOIN et du coup le filtre sur date pourrait poser problème ?

    Exemple, dans ma table ARTICLES j'ai donc un CI_TVA pour la TVA, un CI_TPHBJO pour la TPHBJO et un CI_ECOTAXE pour l'éco-participation.
    Certains articles ne sont pas soumis à ces deux dernières taxes, ma requête serait alors (en admettant que sur la base de la vue que vous proposez, j'aie mis en place une V_TVA_DATE, V_TPHBJO_DATE et V_ECOTAXE_DATE) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT A.* , tva.QF_TAUX, tph.QF_TAUX, eco.QF_TAUX
    FROM ARTICLES A
    INNER JOIN V_TVA_DATE tva
      ON tva.CI_CODE = A.CI_TVA
      AND tva.DateDebut <= @dd_date
      AND (tva.DateFin > @dd_date OR tva.DateFin IS NULL)
    LEFT OUTER JOIN V_TPHBJO_DATE tph
      ON tph.CI_CODE = A.CI_TPHBJO  AND tph.DateDebut <= @dd_date
      AND (tph.DateFin > @dd_date OR tph.DateFin IS NULL)
    LEFT OUTER JOIN V_ECOTAXE_DATE eco
      ON eco.CI_CODE = A.CI_ECOTAXE AND eco.DateDebut <= @dd_date
      AND (eco.DateFin > @dd_date OR eco.DateFin IS NULL)
    Le fait d'ajouter des critères de date ne transforme-t-il pas le LEFT en INNER JOIN puisque l'on a un filtre "absolu" ?

  6. #6
    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
    Citation Envoyé par sbouvetJD Voir le message
    En appliquant cette solution sur une procédure spécifique, le plan d'exécution me donne les résultats suivants :
    requete avec les fonctions : 30.87 %
    requete avec les vues : 69.13 %
    C'est normal, le cout des fonctions n'est pas pris en compte dans les plans d’exécution. Lancez un profiler avec comme seul événement "SQL:BatchCompleted", puis exécutez successivement les deux requêtes et comparez le temps CPU et les IO.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 19/11/2014, 19h23
  2. [Débutant] Valeur calculée sur les dates
    Par pliza dans le forum Développement Sharepoint
    Réponses: 3
    Dernier message: 20/08/2014, 22h54
  3. [AC-2007] Calcul sur une date et obtenir des valeurs pour chaque date obtenue
    Par missalias dans le forum Modélisation
    Réponses: 38
    Dernier message: 07/04/2014, 10h22
  4. [AC-2003] valeur sur date
    Par marcmarc150 dans le forum IHM
    Réponses: 2
    Dernier message: 29/08/2012, 23h11
  5. [AC-2010] probleme avec une valeur null sur une date
    Par kynder surprise dans le forum VBA Access
    Réponses: 3
    Dernier message: 07/05/2012, 18h28

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