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

  1. #1
    Membre à l'essai
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 19
    Points
    19
    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 : 42
    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
    Points : 3 173
    Points
    3 173
    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
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  3. #3
    Membre à l'essai
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 19
    Points
    19
    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
    Points : 13 092
    Points
    13 092
    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 à l'essai
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 19
    Points
    19
    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
    Points : 13 092
    Points
    13 092
    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.

  7. #7
    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 : 42
    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
    Points : 3 173
    Points
    3 173
    Par défaut
    Oui excusez moi, le OUTER APPLY n'est en effet pas disponible en SQL SERVER 2000...
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

  8. #8
    Membre à l'essai
    Homme Profil pro
    Chef de projets MOE/MOA
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    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
    Points : 19
    Points
    19
    Par défaut
    Je les ai lancées 4 fois de suite, un coup l'une l'emporte, un coup l'autre... Au final je pense que ça se vaut ; pour ma part je préfère l'écriture par fonction, mais cela n'étant pas préconisé je vais partir sur les vues.

    Merci !

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 19/11/2014, 18h23
  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, 21h54
  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, 09h22
  4. [AC-2003] valeur sur date
    Par marcmarc150 dans le forum IHM
    Réponses: 2
    Dernier message: 29/08/2012, 22h11
  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, 17h28

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