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

Requêtes MySQL Discussion :

La somme des calculs intermédiaires est plus grande que le total !


Sujet :

Requêtes MySQL

  1. #1
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut La somme des calculs intermédiaires est plus grande que le total !
    Bonjour,

    Je vais devenir chèvre avec mes bovins !

    Structure simplifiée de la table 'detentions' :
    - B_D_FK_IND_BOVINS : l'identifiant du bovin
    - B_D_DAT_ENTR : la date d'entrée dans une exploitation, de type DATE
    - B_D_DAT_SORT : la date de sortie de l'exploitation, de type DATE
    - B_D_FK_IND_CAUSE_SORT : identifiant de la cause de sortie de détention

    1) Nombre de détentions à cause de sortie 2, 3 ou 11 qui ont une détention ultérieure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT COUNT(*)
    FROM bdni2.detentions d1
    WHERE d1.B_D_FK_IND_CAUSE_SORT IN (2, 3, 11)
        AND EXISTS (
            SELECT *
            FROM bdni2.detentions d2
            WHERE d1.B_D_FK_IND_BOVINS = d2.B_D_FK_IND_BOVINS
                AND d2.B_D_DAT_ENTR >= d1.B_D_DAT_SORT
                AND d2.B_D_DAT_ENTR > d1.B_D_DAT_ENTR
        )
    # Résultat : 207 547
    2) Nombre de détentions (d1) à cause de sortie 2, 3 ou 11 qui ont une détention ultérieure (d2) dont la date d'entrée de d2 est égale à la date de sortie de d1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SELECT COUNT(*)
    FROM bdni2.detentions d1
    WHERE d1.B_D_FK_IND_CAUSE_SORT IN (2, 3, 11)
        AND EXISTS (
            SELECT *
            FROM bdni2.detentions d2
            WHERE d1.B_D_FK_IND_BOVINS = d2.B_D_FK_IND_BOVINS
                AND d2.B_D_DAT_ENTR = d1.B_D_DAT_SORT
                AND d2.B_D_DAT_ENTR > d1.B_D_DAT_ENTR
            )
    # Résultat : 50 326 détentions
    3) Nombre de détentions (d1) à cause de sortie 2, 3 ou 11 qui ont une détention ultérieure (d2) dont la date d'entrée de d2 est de 1 à 2 jours après la date de sortie de d1 :
    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
    SELECT COUNT(*)
    FROM bdni2.detentions d1
    WHERE d1.B_D_FK_IND_CAUSE_SORT IN (2, 3, 11)
        AND EXISTS(
            SELECT *
            FROM bdni2.detentions d2
            WHERE d1.B_D_FK_IND_BOVINS = d2.B_D_FK_IND_BOVINS
            AND d2.B_D_DAT_ENTR > d1.B_D_DAT_SORT
            AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 2 DAY) >= d2.B_D_DAT_ENTR
            AND d2.B_D_DAT_ENTR = (
                SELECT MIN(d3.B_D_DAT_ENTR)
                FROM bdni2.detentions d3
                WHERE d3.B_D_FK_IND_BOVINS = d1.B_D_FK_IND_BOVINS
                    AND d3.B_D_DAT_ENTR > d1.B_D_DAT_SORT
                    AND d3.B_D_DAT_ENTR > d1.B_D_DAT_ENTR
            )
        )
    # Résultat : 103 086
    4) Nombre de détentions (d1) à cause de sortie 2, 3 ou 11 qui ont une détention ultérieure (d2) dont la date d'entrée de d2 est de 3 à 7 jours après la date de sortie de d1 :
    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
    SELECT COUNT(*)
    FROM bdni2.detentions d1
    WHERE d1.B_D_FK_IND_CAUSE_SORT IN (2, 3, 11)
        AND EXISTS(
            SELECT *
            FROM bdni2.detentions d2
            WHERE d1.B_D_FK_IND_BOVINS = d2.B_D_FK_IND_BOVINS
            AND d1.B_D_DAT_SORT < d2.B_D_DAT_ENTR
            AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 2 DAY) < d2.B_D_DAT_ENTR
            AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 7 DAY) >= d2.B_D_DAT_ENTR
            AND d2.B_D_DAT_ENTR = (
                SELECT MIN(d3.B_D_DAT_ENTR)
                FROM bdni2.detentions d3
                WHERE d3.B_D_FK_IND_BOVINS = d1.B_D_FK_IND_BOVINS
                    AND d3.B_D_DAT_ENTR > d1.B_D_DAT_SORT
                )
            )
    # Résultat : 33 652
    5) Nombre de détentions (d1) à cause de sortie 2, 3 ou 11 qui ont une détention ultérieure (d2) dont la date d'entrée de d2 est plus de 7 jours après la date de sortie de d1 :
    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
    SELECT COUNT(*)
    FROM bdni2.detentions d1
    WHERE d1.B_D_FK_IND_CAUSE_SORT IN (2, 3, 11)
        AND EXISTS(
            SELECT *
            FROM bdni2.detentions d2
            WHERE d1.B_D_FK_IND_BOVINS = d2.B_D_FK_IND_BOVINS
                AND d1.B_D_DAT_SORT < d2.B_D_DAT_ENTR
                AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 7 DAY) < d2.B_D_DAT_ENTR
                AND d2.B_D_DAT_ENTR = (
                    SELECT MIN(d3.B_D_DAT_ENTR)
                    FROM bdni2.detentions d3
                    WHERE d3.B_D_FK_IND_BOVINS = d1.B_D_FK_IND_BOVINS
                        AND d3.B_D_DAT_ENTR > d1.B_D_DAT_SORT
                )
            )
    # Résultat : 23 496
    Quand j'additionne les résultats 2 à 5 (210 560), je trouve plus que 1 !

    Qu'est-ce qui cloche ?

  2. #2
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Saluton,

    Première piste, COUNT(*) compte probablement un NULL intempestif qqe part.

    Vu la requête, je n'ai pas la prétention d'avoir approfondi l'analyse, c'est juste une remarque réflexe, pour l'instant.

  3. #3
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Finalement je mettrais plutôt en cause cette partie là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
           AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 2 DAY) < d2.B_D_DAT_ENTR
            AND DATE_ADD(d1.B_D_DAT_SORT, INTERVAL 7 DAY) >= d2.B_D_DAT_ENTR
    Je pense que tu ferais mieux de passer par un BETWEEN, en excluant les bornes, bien entendu, donc en jouant sur le nombre de DAY des INTERVALs

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    J'avais pensé évidemment d'abord au BETWEEN mais ce n'est pas un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BETWEEN date1 AND date2
    .
    C'est plutôt du style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BETWEEN date1 AND date1 + X jours
    ou bien encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    BETWEEN date1 + X jours AND date2 + Y jours
    .
    Alors j'ai trouvé la fonction DATE_ADD pour m'en sortir parce qu'avec le BETWEEN j'ai pas trouvé.

  5. #5
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Oui, mais tu peux très bien utiliser la fonction DATE_ADD dans les membres du BETWEEN, en prenant garde au fait que BETWEEN inclus les bornes, c'est ce que je te disais.

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Ca donne les mêmes résultats avec le BETWEEN dans les requêtes 3 et 4 qui ont une plage temporelle bornée. (wow, ça fait chic comme expression non ? )

  7. #7
    Membre expert
    Avatar de Maljuna Kris
    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2005
    Messages
    2 613
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 72
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Novembre 2005
    Messages : 2 613
    Points : 3 950
    Points
    3 950
    Par défaut
    Bon, ben je ne vois plus que remplacer SELECT COUNT(*) par un SELECT COUNT(DISTINCT je ne sais trop quoi) pour supprimer un éventuel doublon intersticiel pervers.
    (Ça vaut la plage temporelle bornée le doublon intersticiel pervers, non ?)

  8. #8
    Expert confirmé Avatar de Cybher
    Homme Profil pro
    Consultant réseaux et sécurité
    Inscrit en
    Mai 2005
    Messages
    3 281
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Consultant réseaux et sécurité
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 281
    Points : 4 644
    Points
    4 644
    Par défaut
    aie, ca s'est compliqué

    je me demandais à quoi servait cette partie de ta requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            AND d2.B_D_DAT_ENTR = (
                SELECT MIN(d3.B_D_DAT_ENTR)
                FROM bdni2.detentions d3
                WHERE d3.B_D_FK_IND_BOVINS = d1.B_D_FK_IND_BOVINS
                    AND d3.B_D_DAT_ENTR > d1.B_D_DAT_SORT
    est elle vraiment utile?

  9. #9
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    Elle sert à ne prendre que la détention suivant celle de d1.

    Mais bon ne cherchez plus.
    J'ai modifié un truc dans la deuxième requête et j'arrive à peu près au total. La différence n'est pas significative pour ce qu'on voulait analyser.

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

Discussions similaires

  1. Ma div de gauche est plus grande que celle de droite sous IE8
    Par beegees dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 26/12/2013, 11h56
  2. Réponses: 4
    Dernier message: 16/04/2013, 16h43
  3. 8 est plus grand que 10
    Par legaramir dans le forum VBA Access
    Réponses: 2
    Dernier message: 23/07/2010, 17h34
  4. 8 est plus grand que 28 ??!!
    Par n@n¤u dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 23/05/2006, 15h14

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