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 :

Requête COUNT avec ORDER BY LIMIT


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut Requête COUNT avec ORDER BY LIMIT
    Bonjour à tous,

    Je bloque sur une requête que je souhaite faire mais il me semble que j'ai une mauvaise approche car le ORDER BY ne semble pas marcher.

    Ici j'ajoute un filtre de plus pour ne viser que MIV087 (car je sais qu'il y a 2 entrées mais ne doit sortir que 1).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT
    	COUNT(*) AS nbpresent,
    	(SELECT COUNT(*) FROM equipement WHERE equipement.periodicite >=1) As nbtotal
    	FROM equipement 
    	INNER JOIN equipementaction ON equipement.codeidentifiant = equipementaction.codeidentifiant
    	WHERE equipement.periodicite >= 1
    		AND equipement.codeidentifiant LIKE 'MIV087'
    		AND (CURDATE() <= ADDDATE(equipementaction.actiondate, INTERVAL equipement.periodicite MONTH))
    	ORDER BY equipementaction.actiondate DESC LIMIT 0, 1
    Les données concernent 2 tables : equipement (une entrée unique par equipement) et equipementaction (+sieurs entrées par équipement)
    table equipement:
    ... codeidentifiant periodicite ...
    ... MIV087 12 ...

    table equipementaction: (champ actiondate format date)
    ... codeidentifiant actiondate ...
    ... MIV087 2016-04-01 ...
    ... MIV087 2016-03-03 ...
    Pour information, la date d'action fait parti du filtre car je recherche les équipements ayant une action à jour. En effet, le champ periodicite étant le nombre de mois où il faut faire un contrôle/suivi (délais ici tout les 12 mois) auquel je rajoute (ADDDATE) ce nombre de mois au champ actiondate (derniere action enregistrée) pour avoir equipement dont la derniere date d'action (de suivi ou autre) est inférieure au délais (de 12 mois) selon la date en cours (CURDATE<= ...).

    Je souhaite comptabiliser 1 avec la requête grace à l'emploi de ORDER BY actiondate DESC LIMIT 1 (pour ne compter que le plus récent)
    Mais cela ne marche pas (me donne 2). Si j'enlève ORDER BY DESC LIMIT, cela me donne aussi 2 (comme si cela ne changait rien). Remarque, si je mets offset 1 (LIMIT 1, 1) cela ne me donne plus rien (alors que devrais me donner 1 je pense, le second de la liste).
    J'ai bien 2 entrées dont la date est <= à la date d'aujourd'hui + 12 mois, mais je ne souhaite ne compter que le plus récent.

    Merci à celui qui peut me dire comment faire.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Bon j'ai modifié un peu la requete comme suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT
    	COUNT(DISTINCT equipementaction.codeidentifiant) AS nbpresent,
    	(SELECT COUNT(*) FROM equipement WHERE equipement.periodicite >=1) As nbtotal
    	FROM equipement 
    	INNER JOIN equipementaction ON equipement.codeidentifiant = equipementaction.codeidentifiant
    	WHERE equipement.periodicite >= 1
    		AND equipement.codeidentifiant LIKE 'MIV087'
    		AND (CURDATE() <= ADDDATE(equipementaction.actiondate, INTERVAL equipement.periodicite MONTH))
    Donc avec DISTINCT au lieu de ORDER BY date DESC LIMIT 1
    Ca me donne ce que je recherche mais c'est un peu alambiqué comme moyen !

    Je souhaite toujours savoir pourquoi avec ORDER BY cela ne marche pas, merci.

  3. #3
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 010
    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 010
    Billets dans le blog
    6
    Par défaut
    LIMIT n'existe pas en SQL... je suppose que vous êtes sur MySQmerde ?

    Commencez donc par respecter la charte de postage...
    http://www.developpez.net/forums/a69...gage-sql-lire/

    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/ * * * * *

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Bonjour,
    Oui en mysql.

    Faut'il changer de forum ? si oui, pouvez vous basculer la discution au bon endroit, sinon je ferais un autre dans mysql. Merci.

    La derniere solution n'est pas bonne, car j'ai d'autres requetes où il me faut le nombre d'équipement ayant le dernier état (de conformité). Le distinct ne me permet pas de faire ça, seul la derniere action m'interesse (que je veux faire avec order by date desc limit mais qui ne marche pas)

  5. #5
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut à tous.

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
            DEFAULT CHARACTER SET `latin1`
            DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `equipement`
    --------------
     
    --------------
    CREATE TABLE `equipement`
    (
      `id`               integer  unsigned NOT NULL AUTO_INCREMENT primary key,
      `codeidentifiant`  varchar(255)      NOT NULL,
      `periodicite`      smallint unsigned NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `equipement` (`codeidentifiant`,`periodicite`) values
      ('MIV075',  6),
      ('MIV080',  6),
      ('MIV087', 12)
    --------------
     
    --------------
    select * from equipement
    --------------
     
    +----+-----------------+-------------+
    | id | codeidentifiant | periodicite |
    +----+-----------------+-------------+
    |  1 | MIV075          |           6 |
    |  2 | MIV080          |           6 |
    |  3 | MIV087          |          12 |
    +----+-----------------+-------------+
    --------------
    DROP TABLE IF EXISTS `equipementaction`
    --------------
     
    --------------
    CREATE TABLE `equipementaction`
    (
      `id`               integer  unsigned NOT NULL AUTO_INCREMENT primary key,
      `codeidentifiant`  varchar(255)      NOT NULL,
      `actiondate`       date              NOT NULL
    ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    INSERT INTO `equipementaction` (`codeidentifiant`,`actiondate`) values
      ('MIV075', '2015-11-01'),
      ('MIV075', '2015-10-01'),
      ('MIV075', '2015-09-01'),
      ('MIV080', '2016-07-01'),
      ('MIV080', '2016-06-01'),
      ('MIV080', '2016-05-01'),
      ('MIV080', '2016-04-01'),
      ('MIV080', '2016-03-01'),
      ('MIV080', '2016-02-01'),
      ('MIV087', '2016-04-01'),
      ('MIV087', '2016-03-03')
    --------------
     
    --------------
    select * from equipementaction
    --------------
     
    +----+-----------------+------------+
    | id | codeidentifiant | actiondate |
    +----+-----------------+------------+
    |  1 | MIV075          | 2015-11-01 |
    |  2 | MIV075          | 2015-10-01 |
    |  3 | MIV075          | 2015-09-01 |
    |  4 | MIV080          | 2016-07-01 |
    |  5 | MIV080          | 2016-06-01 |
    |  6 | MIV080          | 2016-05-01 |
    |  7 | MIV080          | 2016-04-01 |
    |  8 | MIV080          | 2016-03-01 |
    |  9 | MIV080          | 2016-02-01 |
    | 10 | MIV087          | 2016-04-01 |
    | 11 | MIV087          | 2016-03-03 |
    +----+-----------------+------------+
    --------------
    select codeidentifiant,
           date_sub(current_date, interval tb1.periodicite month) as date_min,
                    current_date                                  as date_max
    from       equipement        as tb1
    order by codeidentifiant
    --------------
     
    +-----------------+------------+------------+
    | codeidentifiant | date_min   | date_max   |
    +-----------------+------------+------------+
    | MIV075          | 2015-12-02 | 2016-06-02 |
    | MIV080          | 2015-12-02 | 2016-06-02 |
    | MIV087          | 2015-06-02 | 2016-06-02 |
    +-----------------+------------+------------+
    --------------
    select tb1.codeidentifiant,
           max(tb2.actiondate) as actiondate
    from       equipement        as tb1
    inner join equipementaction  as tb2
    ON tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate between date_sub(current_date, interval tb1.periodicite month) and current_date
     
    group by tb1.codeidentifiant
    --------------
     
    +-----------------+------------+
    | codeidentifiant | actiondate |
    +-----------------+------------+
    | MIV080          | 2016-06-01 |
    | MIV087          | 2016-04-01 |
    +-----------------+------------+
    --------------
    select codeidentifiant,
           count(*) as nbpresent
    from (
     
      select tb1.codeidentifiant,
             max(tb2.actiondate) as actiondate
      from       equipement        as tb1
      inner join equipementaction  as tb2
      ON tb2.codeidentifiant = tb1.codeidentifiant
     
      where tb1.periodicite is not null
        and tb2.actiondate between date_sub(current_date, interval tb1.periodicite month) and current_date
     
      group by tb1.codeidentifiant
     
    ) as x
     
    group by codeidentifiant
    order by codeidentifiant
    --------------
     
    +-----------------+-----------+
    | codeidentifiant | nbpresent |
    +-----------------+-----------+
    | MIV080          |         1 |
    | MIV087          |         1 |
    +-----------------+-----------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
     
    Appuyez sur une touche pour continuer...
    @+

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Bonjour Artemus,
    Merci pour ta réponse qui est très bien détaillée.

    Ce que je veux comme sortie c'est uniquement une ligne avec nbpresent (selon condition, ici exemple si contrôle à jour avec dernière date du contrôle combiné avec périodicité des contrôles) et nbtotal (le nombre des equipement enregistrés), ce qui me dira qu'il y a x% des equipements à jour (sans me dire en détaille lesquels)

    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
    22
    23
     
    table equipement :
    +----+-----------------+-------------+
    | id | codeidentifiant | periodicite |
    +----+-----------------+-------------+
    |  1 | MIV087          |          12 |
    +----+-----------------+-------------+
     
    table equipementaction :
    +----+-----------------+------------+
    | id | codeidentifiant | actiondate |
    +----+-----------------+------------+
    | 01 | MIV087          | 2016-04-01 |
    | 02 | MIV087          | 2016-03-03 |
    +----+-----------------+------------+
     
    sortie :
    +----------+--------+
    | nbpresent| nbtotal|
    +----------+--------+
    |     1    |    1   |
    +----------+--------+
    soit 1 équipement à jour sur 1 (100%)
    En faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT
    	COUNT(DISTINCT equipementaction.codeidentifiant) AS nbpresent,
    	(SELECT COUNT(*) FROM equipement WHERE equipement.periodicite >=1) As nbtotal
    	FROM equipement 
    	INNER JOIN equipementaction ON equipement.codeidentifiant = equipementaction.codeidentifiant
    	WHERE equipement.periodicite >= 1
    		AND equipement.codeidentifiant LIKE 'MIV087'
    		AND (CURDATE() <= ADDDATE(equipementaction.actiondate, INTERVAL equipement.periodicite MONTH))
    Cela me donne ce que je cherche, mais j'aurais préférer la première requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT
    	COUNT(*) AS nbpresent,
    	(SELECT COUNT(*) FROM equipement WHERE equipement.periodicite >=1) As nbtotal
    	FROM equipement 
    	INNER JOIN equipementaction ON equipement.codeidentifiant = equipementaction.codeidentifiant
    	WHERE equipement.periodicite >= 1
    		AND equipement.codeidentifiant LIKE 'MIV087'
    		AND (CURDATE() <= ADDDATE(equipementaction.actiondate, INTERVAL equipement.periodicite MONTH))
    	ORDER BY equipementaction.actiondate DESC LIMIT 0, 1
    Mais celle-ci ne marche pas (me donne nbpresent = 2 et nbtotal = 1). En effet, il s'avère que le COUNT est agrégateur et qu'on ne peut pas faire un ORDER BY et LIMIT (car obligatoirement qu'1 ligne à la fin).
    Hier, j'ai trouvé une info parlant de ça (voir lien : http://www.mysqldiary.com/limited-select-count/). Je vais me remettre dessus.

    Encore merci.

  7. #7
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut lukeabate.

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    CURDATE() <= ADDDATE(equipementaction.actiondate, INTERVAL equipement.periodicite MONTH)

    1) ton calcul est mal posé. Pour des questions de performances, on ne modifie pas la colonne de la table comme tu le fais, mais plutôt la variable curdate().
    Pourquoi ? Car à chaque ligne, MySql va faire le calcul et cela va prendre du temps pour rien !

    Prenons un exemple pour détailler le calcul.
    La date du jour est le '2016-06-03'. Tu veux la comparer à la date action du '2016-04-01' sur une périodicité de 12 mois.
    La date action devient : '2016-04-01' + 12 mois ==> '2017-04-01'.
    La comparaison donne : '2016-06-03' <= '2017-04-01'.

    Maintenant, si tu procèdes à l'envers, voici ce que cela done :
    La date du jour est le '2016-06-03'. Tu retranches la périodicité de 12 mois.
    Ce qui donne : '2016-06-03' - 12 mois ==> '2015-06-03'.
    La comparaison donne : '2015-06-03' <= '2016-04-01'.

    Le résultat est exactement le même, sauf que tu ne modifies pas la colonne date 'actiondate' à chaque ligne.

    La bonne pratique est la suivante :
    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    and tb2.actiondate between date_sub(current_date, interval tb1.periodicite month) and current_date

    2) voici la table des équipements, celle de mon jeu d'essai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    +----+-----------------+-------------+
    | id | codeidentifiant | periodicite |
    +----+-----------------+-------------+
    |  1 | MIV075          |           6 |
    |  2 | MIV080          |           6 |
    |  3 | MIV087          |          12 |
    +----+-----------------+-------------+
    Comme tu le constates, il y a trois lignes et c'est ce que tu recherches dans la colonne "nbtotal".

    Et voici la table produite par ma requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    +-----------------+------------+
    | codeidentifiant | actiondate |
    +-----------------+------------+
    | MIV080          | 2016-06-01 |
    | MIV087          | 2016-04-01 |
    +-----------------+------------+
    Ici, il y a seulement deux lignes, et ce résultat sera celle de la colonne "nbpresent".


    Il est simple d'associer ces deux tables afin de produire le résultat que tu recherches, à savoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |       3 |         2 |
    +---------+-----------+
    Comment obtenir ce résultat ?
    A partir de ma requête, il suffit de faire une jointure sur la table équipement.
    Mais pas n'importe quelle jointure, une jointure de type "left outer join".
    En partant de la table équipement, tu auras toutes les lignes.
    En faisant cette jointure, tu vas te retrouver avec deux cas :
    --> soit la valeur de la colonne "codeidentifiant" existe dans la requête, et dans ce cas là, tu auras la ligne.
    --> soit il n'y a aucune correspondance et dans ce cas, tu récupères une ligne contenant que des nulls.

    J'espère que c'est bien ce que tu désires obtenir comme résultat.
    Je ne te remets pas la totalité du script, mais juste la requête :
    Code mysql : 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
    22
    23
    24
    25
    26
    27
    --------------
    select count(tb3.codeidentifiant) as nbtotal,
           count(tb4.actiondate)      as nbpresent
     
    from            equipement as tb3
    left outer join (
     
        select tb1.codeidentifiant,
               max(tb2.actiondate)   as actiondate
        from       equipement        as tb1
        inner join equipementaction  as tb2
        on tb2.codeidentifiant = tb1.codeidentifiant
     
        where tb1.periodicite is not null
          and tb2.actiondate between date_sub(current_date, interval tb1.periodicite month) and current_date
     
        group by tb1.codeidentifiant
     
    ) as tb4
    on tb4.codeidentifiant = tb3.codeidentifiant
    --------------
     
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |       3 |         2 |
    +---------+-----------+
    Il n'y a aucune difficulté dans ce que tu recherches, mais il faut faire les choses étapes par étapes.

    @+

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Un grand merci, j'ai mis ta requête et cela semble bien marcher. Faut que je regarde bien pour comprendre (notament le left outer join).
    Tu mérite bien 5/5.

    Ok, je comprends pour la recherche date (regarde si pas trop vieille en soustrayant curdate avec 'periodicite', au lieu d'ajouter a 'actiondate' 'periodicite').

    Encore merci

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Bonjour, me revoilà :aie:

    Artemus encore merci pour la réponse et résolution à ma requête.

    Toutefois, je voudrais maintenant ajouter un filtre supplémentaire (en plus de compter si suivi équipement à jour ou pas).
    En effet, j'ai un champ 'état' (conforme, non conforme et réformé). Je voudrais savoir, combien d'équipement sont à jour et pour quel état.

    Il peut en effet avoir plusieurs actions (table equipementaction : codeidentifiant, dateaction et état) étant entre currentdate-periodicite et currentdate (donc à jour)
    Dans ta requête, tu as groupé par codeidentifiant.

    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
    22
     
    select count(tb3.codeidentifiant) as nbtotal,
           count(tb4.actiondate)      as nbpresent
     
    from            equipement as tb3
    left outer join (
     
        select tb1.codeidentifiant,
               max(tb2.actiondate)   as actiondate
        from       equipement        as tb1
        inner join equipementaction  as tb2
        on tb2.codeidentifiant = tb1.codeidentifiant
     
        where tb1.periodicite is not null
          and tb2.actiondate between date_sub(current_date, interval tb1.periodicite month) and current_date
          "
          and (tb2.etat LIKE 'conforme' OR tb2.etat LIKE 'non conforme' OR tb2.etat LIKE 'réformé')
          "
        group by tb1.codeidentifiant
     
    ) as tb4
    on tb4.codeidentifiant = tb3.codeidentifiant
    quand je mets les 3 état (conforme ou non conforme ou réformé) cela me donne 42
    quand je mets que pour conforme : me donne 36
    quand je mets que pour non conforme : me donne 6
    et pour réformé : cela me donne 2
    soit 44 (et pas 42)

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 132
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 132
    Par défaut
    Bonjour,

    Ça n'a l'air de choquer personne à part moi mais : pourquoi faire un ORDER BY pour une requête COUNT ?

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Citation Envoyé par devyan Voir le message
    Bonjour,

    Ça n'a l'air de choquer personne à part moi mais : pourquoi faire un ORDER BY pour une requête COUNT ?
    Bonjour devyan,
    Pour répondre à ta question, je voulais savoir le nombre d'équipements (lesquels ont plusieurs entrées avec dates) ayant une entrée à jour (mais comme plusieurs possible pour un équipement ne prendre que la plus récente).
    Dès la première solution à mon problème, il n'y a pas eu de ORDER BY de proposé.

  12. #12
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut à tous.

    Citation Envoyé par devyan
    Ça n'a l'air de choquer personne à part moi mais : pourquoi faire un ORDER BY pour une requête COUNT ?
    Où voyez-vous un "order by" dans ma solution ?

    Citation Envoyé par lukeabate
    quand je mets les 3 état (conforme ou non conforme ou réformé) cela me donne 42
    quand je mets que pour conforme : me donne 36
    quand je mets que pour non conforme : me donne 6
    et pour réformé : cela me donne 2
    soit 44 (et pas 42)
    Je ne peux rien pour vous si vous ne me donnez pas un jeu d'essai représentatif de votre problème.

    Et donnez moi aussi l'énoncé exacte et final de ce que vous désirez faire.

    @+

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Bonjour Artemus,
    Je vous ai envoyé des données en MP (mais comme limité en nb caractère, j'ai du effacer des trucs).

    Je souhaite avoir, comme avant le nombre d'equipement à jour (nbpresent, selon current date et periodocite) mais maintenant aussi selon le champ etat (si conforme, non conforme ou réformé)
    exemple :
    Nom : Presse-papier01.png
Affichages : 367
Taille : 27,9 Ko

  14. #14
    Membre Expert
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 132
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 132
    Par défaut
    Citation Envoyé par Artemus24 Voir le message


    Où voyez-vous un "order by" dans ma solution ?

    Dans cette solution nulle part, donc aucune raison de se sentir visé

    Ma remarque concernait le code initial et le titre du sujet mais lukeabate a déjà répondu
    A+

  15. #15
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut lukeabate.

    J'ai modifié la requête afin de sélectionner la ligne ayant la plus grande date dans l'intervalle donnée.
    De plus, je sélectionne dans cette sous-requête, la colonne "etat" à la valeur que tu désires.

    Ton jeu d'essai n'est pas conforme à ce que tu désires obtenir. Il n'y a qu'une seule ligne qui soit sélectionnable :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    --------------
    select tb1.codeidentifiant,
           tb1.periodicite,
           date_sub(current_date, interval tb1.periodicite month) as dateinf,
           tb2.actiondate
     
    from            equipement        as tb1
    left outer join equipementaction  as tb2
    on tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
        where  tb3.actiondate >= date_sub(current_date, interval tb1.periodicite month)
          and  tb3.codeidentifiant = tb2.codeidentifiant
     
    )
     
    order by tb1.codeidentifiant
    --------------
     
    +-----------------+-------------+------------+------------+
    | codeidentifiant | periodicite | dateinf    | actiondate |
    +-----------------+-------------+------------+------------+
    | MIV035          |           6 | 2015-12-07 | 2016-06-01 |
    +-----------------+-------------+------------+------------+
     
    Appuyez sur une touche pour continuer...
    La plupart des lignes ont "actiondate" à la valeur de 2011.

    Je préfère que tu m'envoies un jeu d'essai bien plus complet avec une périodicité conforme à ce que tu attends.

    Mon adresse email : artemus @ jcz.fr

    @+

  16. #16
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut lukeabate.

    J'ai supprimé ce calcul de la périodicité qui me pose des problèmes avec ce jeu d'essai.
    J'ai fait une comptabilisation de ton fameux problème. Voici le résultat :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
     
    --------------
    select count(*)
    from            equipement        as tb1
    left outer join equipementaction  as tb2
    on tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
        where  tb3.codeidentifiant = tb2.codeidentifiant
     
    )
    --------------
     
    +----------+
    | count(*) |
    +----------+
    |       38 |
    +----------+
    --------------
    select count(*)
    from            equipement        as tb1
    left outer join equipementaction  as tb2
    on tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
        where  tb3.codeidentifiant = tb2.codeidentifiant
          and  tb3.etat = 'conforme'
     
    )
    --------------
     
    +----------+
    | count(*) |
    +----------+
    |       36 |
    +----------+
    --------------
    select count(*)
    from            equipement        as tb1
    left outer join equipementaction  as tb2
    on tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
        where  tb3.codeidentifiant = tb2.codeidentifiant
          and  tb3.etat = 'non conforme'
     
    )
    --------------
     
    +----------+
    | count(*) |
    +----------+
    |        2 |
    +----------+
    --------------
    select count(*)
    from            equipement        as tb1
    left outer join equipementaction  as tb2
    on tb2.codeidentifiant = tb1.codeidentifiant
     
    where tb1.periodicite is not null
      and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
        where  tb3.codeidentifiant = tb2.codeidentifiant
          and  tb3.etat = 'réformé'
     
    )
    --------------
     
    +----------+
    | count(*) |
    +----------+
    |        1 |
    +----------+
     
    Appuyez sur une touche pour continuer...
    Pourquoi 1 + 2 + 36 = 39 n'est pas égale au 38 de la requête général (sans restriction) ?

    La réponse est qu'il existe un code identifiant ayant plusieurs lignes dans ta table "equipementaction" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    --------------
    select id, codeidentifiant, actiondate, etat
    from equipementaction
    where codeidentifiant = 'miv035'
    --------------
     
    +-----+-----------------+------------+--------------+
    | id  | codeidentifiant | actiondate | etat         |
    +-----+-----------------+------------+--------------+
    | 430 | MIV035          | 2012-12-19 | conforme     |
    | 674 | MIV035          | 2016-06-01 | non conforme |
    +-----+-----------------+------------+--------------+
    Ce code identifiant "miv035" sera comptabilisé aussi bien sur 'conforme' que sur 'non conforme'.
    Donc séparément tu comptabilises deux lignes, tandis que dans le général, tu comptabilises une seule ligne.

    Ce n'est pas un problème, mais vu que cela te semblait une anomalie, il faut maintenant que tu me dises comment tu désires traiter ce doublon ?
    Peut-être que tu désires, non plus sélectionner dans la sous-requête la plus interne le "etat", mais le faire dans le résultat final.
    Dans ce cas, il y aura bien des intersections vides entre tes trois "etat".

    @+

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    ...
    Ce code identifiant "miv035" sera comptabilisé aussi bien sur 'conforme' que sur 'non conforme'.
    Donc séparément tu comptabilises deux lignes, tandis que dans le général, tu comptabilises une seule ligne.

    Ce n'est pas un problème, mais vu que cela te semblait une anomalie, il faut maintenant que tu me dises comment tu désires traiter ce doublon ?
    Bonjour Artemus,
    Je souhaite ne tenir compte que de la dernière action.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    +-----+-----------------+------------+--------------+
    | id  | codeidentifiant | actiondate | etat         |
    +-----+-----------------+------------+--------------+
    | 430 | MIV035          | 2012-12-19 | conforme     |
    | 674 | MIV035          | 2016-06-01 | non conforme |
    +-----+-----------------+------------+--------------+
    Ici seule la deuxième ligne suffit, car étant la dernière action enregistré (c pour ça que je voulais order by date desc limit 1 pour ne prendre que l'info la plus récente, puis un filtre avec periodicite pour dire si à jour ou pas: délais dépassé).
    Dans cet exemple (2016-06-01) c'est la dernière action, de plus elle est à jour (car periodicite tout les 6 ou 12 mois). Donc quand je veux compter conforme, cet équipement ne doit pas être comptabilisé (seulement comptabilisé comme non conforme).

  18. #18
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut lukeabate.

    La ligne sélectionnée par le critère du maximum de la colonne "actiondate", aura aussi comme autre critère celui de la colonne "etat".
    Ainsi il n'y aura pas d'ambiguïté sur la comptabilisation des résultats, soit pris globalement, soit par etat.
    Ci-après, la colonne "nbpresent" est maintenant correctement comptabilisée : 1 + 2 + 35 = 38.
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    --------------
    select count(tb4.codeidentifiant) as nbtotal,
           count(tb5.actiondate)      as nbpresent
     
    from equipement as tb4
    left outer join (
     
      select tb1.codeidentifiant,
             tb2.actiondate        as actiondate
      from       equipement        as tb1
      inner join equipementaction  as tb2
      on tb2.codeidentifiant = tb1.codeidentifiant
     
      where tb1.periodicite is not null
        and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
          where  tb3.codeidentifiant = tb1.codeidentifiant
      )
    ) as tb5
    on tb5.codeidentifiant = tb4.codeidentifiant
    --------------
     
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |      41 |        38 |
    +---------+-----------+
    --------------
    select count(tb4.codeidentifiant) as nbtotal,
           count(tb5.actiondate)      as nbpresent
     
    from equipement as tb4
    left outer join (
     
      select tb1.codeidentifiant,
             tb2.actiondate        as actiondate
      from       equipement        as tb1
      inner join equipementaction  as tb2
      on tb2.codeidentifiant = tb1.codeidentifiant
     
      where tb1.periodicite is not null
        and tb2.etat = 'conforme'
        and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
          where  tb3.codeidentifiant = tb1.codeidentifiant
      )
    ) as tb5
    on tb5.codeidentifiant = tb4.codeidentifiant
    --------------
     
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |      41 |        35 |
    +---------+-----------+
    --------------
    select count(tb4.codeidentifiant) as nbtotal,
           count(tb5.actiondate)      as nbpresent
     
    from equipement as tb4
    left outer join (
     
      select tb1.codeidentifiant,
             tb2.actiondate        as actiondate
      from       equipement        as tb1
      inner join equipementaction  as tb2
      on tb2.codeidentifiant = tb1.codeidentifiant
     
      where tb1.periodicite is not null
        and tb2.etat = 'non conforme'
        and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
          where  tb3.codeidentifiant = tb1.codeidentifiant
      )
    ) as tb5
    on tb5.codeidentifiant = tb4.codeidentifiant
    --------------
     
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |      41 |         2 |
    +---------+-----------+
    --------------
    select count(tb4.codeidentifiant) as nbtotal,
           count(tb5.actiondate)      as nbpresent
     
    from equipement as tb4
    left outer join (
     
      select tb1.codeidentifiant,
             tb2.actiondate        as actiondate
      from       equipement        as tb1
      inner join equipementaction  as tb2
      on tb2.codeidentifiant = tb1.codeidentifiant
     
      where tb1.periodicite is not null
        and tb2.etat = 'réformé'
        and tb2.actiondate = (
     
        select max(tb3.actiondate) as actiondate
        from   equipementaction as tb3
          where  tb3.codeidentifiant = tb1.codeidentifiant
      )
    ) as tb5
    on tb5.codeidentifiant = tb4.codeidentifiant
    --------------
     
    +---------+-----------+
    | nbtotal | nbpresent |
    +---------+-----------+
    |      41 |         1 |
    +---------+-----------+
     
    Appuyez sur une touche pour continuer...
    @+

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 28
    Par défaut
    Citation Envoyé par Artemus24 Voir le message
    La ligne sélectionnée par le critère du maximum de la colonne "actiondate", aura aussi comme autre critère celui de la colonne "etat".
    Ainsi il n'y aura pas d'ambiguïté sur la comptabilisation des résultats, soit pris globalement, soit par etat.
    Ci-après, la colonne "nbpresent" est maintenant correctement comptabilisée : 1 + 2 + 35 = 38.
    Edit: ça fonctionne ! (je m'étais trompé car au début je n'avais pas mis pour celle globale etat=conforme or non conforme or reformé; puisqu'il y a d'autres trucs que je ne veux pas regarder: la base n'est pas à jour)

    Nom : Presse-papier01.png
Affichages : 371
Taille : 15,8 Ko


    Avec le filtre currentdate selon periodicite : me donne bien 36+4+2=42

    Nom : Presse-papier01.png
Affichages : 364
Taille : 15,5 Ko
    Images attachées Images attachées  

  20. #20
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 917
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 917
    Par défaut
    Salut lukeabate.

    Citation Envoyé par lukeabate
    Edit: ça fonctionne !
    Tant mieux. Je suis heureux pour toi.

    Tu peux mettre ce sujet à résolu.

    @+

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. JOIN ON avec ORDER et LIMIT
    Par xxkirastarothxx dans le forum Requêtes
    Réponses: 4
    Dernier message: 21/12/2009, 18h28
  2. Requête: Count avec un IF et Distinct
    Par Sethenssen dans le forum Requêtes
    Réponses: 8
    Dernier message: 04/11/2009, 13h35
  3. [MySQL] Requête COUNT avec LIMIT
    Par oim dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 31/12/2007, 00h24
  4. Problème de requête count(*) avec DB2
    Par elsodiop dans le forum DB2
    Réponses: 3
    Dernier message: 30/11/2006, 16h11
  5. [Requête]Problème avec ORDER BY NZ
    Par arnaud_verlaine dans le forum C++Builder
    Réponses: 5
    Dernier message: 20/11/2006, 20h27

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