Partage
  • Partager sur Facebook
  • Partager sur Twitter

Server has gone away

    24 novembre 2010 à 12:09:14

    Salut,
    Je travaille sur une grosse base de données et lorsque j'effectue une requête sur phpmyadmin, j'obtiens un message d'erreur ('Server has gone away').
    Voici ma requête :

    select count(a.status), count(b.status) from blabla a, blabla b 
    where a.status = 'refuse' and b.status = 'facturable';
    


    J'ai essayé sur la commande mysql, mais cela ne fonctionne pas (l'attente est super longue et ça me fait laguer le pc).
    Y a t-il un moyen d'effectuer la requête sans avoir ce message ?
    Merci d'avance.
    • Partager sur Facebook
    • Partager sur Twitter
      24 novembre 2010 à 12:11:50

      Fais 2 requêtes plutôt... Parce qu'une jointure sans jointure, si t'as beaucoup de lignes, forcément ça prend du temps...
      • Partager sur Facebook
      • Partager sur Twitter
        24 novembre 2010 à 12:41:20

        J'ai changé ma requête, elle fonctionne :
        select count(status) from blabla where status = 'refuse'
        UNION
        select count(status) from blabla where status = 'facturable';
        


        J'aimerais en fait, faire un calcul avec ces deux requêtes.
        Comment vais-je procéder ?
        • Partager sur Facebook
        • Partager sur Twitter
          24 novembre 2010 à 13:35:39

          Qu'est-ce que t'appelles un calcul... ??
          • Partager sur Facebook
          • Partager sur Twitter
            24 novembre 2010 à 13:43:05

            Je souhaite par exemple additionner les deux count(status) en tenant compte bien sûr de la taille de la base.
            • Partager sur Facebook
            • Partager sur Twitter
              24 novembre 2010 à 13:45:19

              select SUM(t.nb) FROM (
              select count(status) as nb from blabla where status = 'refuse'
              UNION
              select count(status) as nb from blabla where status = 'facturable') as t;
              
              • Partager sur Facebook
              • Partager sur Twitter
                25 novembre 2010 à 0:09:41

                Merci, ça fonctionne.
                J'aimerai faire ce calcul, pourrais tu m'aider stp.

                [count(refuse) / [count(refuse) + count(facturable)]] * 100

                • Partager sur Facebook
                • Partager sur Twitter
                  25 novembre 2010 à 8:36:49

                  Fais-le en deux requêtes et effectue le calcul hors SQL.

                  Parce que sinon je ne vois que cette solution-là et... je la trouve excessivement moche et pas optimisée :
                  select 100 * z.refuse / (z.refuse+z.facturable) from (
                  select 
                  count(if(status='refuse', 'refuse', null)) as refuse, 
                  count(if(status='facturable', 'facturable', null)) as facturable
                  from tatable
                  ) z;
                  • Partager sur Facebook
                  • Partager sur Twitter
                    25 novembre 2010 à 10:58:00

                    Merci de m'avoir aidé.
                    En fait, pourquoi elle n'est pas optimisée ?
                    • Partager sur Facebook
                    • Partager sur Twitter
                      25 novembre 2010 à 11:10:51

                      Citation

                      En fait, pourquoi elle n'est pas optimisée ?


                      Parce qu'il y a une sous-requête. JE pense qu'on doit pouvoir faire sans...
                      • Partager sur Facebook
                      • Partager sur Twitter
                        26 novembre 2010 à 13:10:44

                        Citation : QuentinC 2


                        Parce que sinon je ne vois que cette solution-là et... je la trouve excessivement moche et pas optimisée :

                        select 100 * z.refuse / (z.refuse+z.facturable) from (
                        select 
                        count(if(status='refuse', 'refuse', null)) as refuse, 
                        count(if(status='facturable', 'facturable', null)) as facturable
                        from tatable
                        ) z;


                        Effectivement, les expressions dans les count sont moches, et ce n'est pas indexable. Il vaudrait mieux faire :

                        SELECT status, count(*) AS cnt FROM table WHERE status IN ('refuse','facturable') GROUP BY status


                        et réaliser le calcul en PHP. Ou mettre un CTE, mais je suppose que tu es sous MySQL...
                        • Partager sur Facebook
                        • Partager sur Twitter
                          26 novembre 2010 à 13:21:43

                          Citation

                          Ou mettre un CTE, mais je suppose que tu es sous MySQL...


                          Question de curiosité, c'est quoi un CTE ? Une sorte de procédure stockée ?
                          Pardonne mon ignorance, mais je n'ai jamais utilisé d'autre SGBDR que MySQL ...
                          • Partager sur Facebook
                          • Partager sur Twitter
                            26 novembre 2010 à 13:38:22

                            C'est le fait de créer des tables virtuelles (common table expression) que tu peux ensuite requêter, un peu comme une table temporaire, mais en beaucoup moins lourd :

                            test=> CREATE TABLE bobo ( status TEXT );
                            test=> INSERT INTO bobo SELECT 'refuse' FROM generate_series( 1,10000 );
                            test=> INSERT INTO bobo SELECT 'facturable' FROM generate_series( 1,1000 );
                            test=> INSERT INTO bobo SELECT 'bidon' FROM generate_series( 1,10000 );
                            test=> CREATE INDEX bobo_status ON bobo( status );
                            test=> VACUUM ANALYZE bobo;
                            
                            test=> WITH stats AS (SELECT status, count(*) FROM bobo WHERE status IN ('refuse','facturable') GROUP BY status) SELECT * FROM stats;
                               status   | count 
                            ------------+-------
                             refuse     | 10000
                             facturable |  1000
                            (2 lignes)
                            
                            test=> WITH
                            stats1 AS 
                             (SELECT status, count(*) AS total FROM bobo WHERE status IN ('refuse','facturable') GROUP BY status),
                            stats2 AS 
                              (SELECT 
                                (SELECT total FROM stats1 WHERE status='refuse') AS refuse, 
                                (SELECT total FROM stats1 WHERE status='facturable') AS facturable
                              )
                            SELECT *, 100 * refuse / (refuse+facturable) FROM stats2;
                                                                                           ^
                             refuse | facturable | ?column? 
                            --------+------------+----------
                              10000 |       1000 |       90
                            (1 ligne)
                            
                            Temps : 7,506 ms
                            
                            test=> EXPLAIN ANALYZE WITH
                            stats1 AS 
                             (SELECT status, count(*) AS total FROM bobo WHERE status IN ('refuse','facturable') GROUP BY status),
                            stats2 AS 
                              (SELECT 
                                (SELECT total FROM stats1 WHERE status='refuse') AS refuse, 
                                (SELECT total FROM stats1 WHERE status='facturable') AS facturable
                              )
                            SELECT *, 100 * refuse / (refuse+facturable) FROM stats2;
                                                                                  QUERY PLAN                                                      
                            ----------------------------------------------------------------------------------------------------------------------
                             CTE Scan on stats2  (cost=409.25..409.27 rows=1 width=16) (actual time=8.330..8.331 rows=1 loops=1)
                               CTE stats1
                                 ->  HashAggregate  (cost=409.12..409.14 rows=2 width=6) (actual time=8.313..8.313 rows=2 loops=1)
                                       ->  Seq Scan on bobo  (cost=0.00..356.50 rows=10524 width=6) (actual time=0.009..5.041 rows=11000 loops=1)
                                             Filter: (status = ANY ('{refuse,facturable}'::text[]))
                               CTE stats2
                                 ->  Result  (cost=0.09..0.10 rows=1 width=0) (actual time=8.326..8.327 rows=1 loops=1)
                                       InitPlan 2 (returns $1)
                                         ->  CTE Scan on stats1  (cost=0.00..0.04 rows=1 width=8) (actual time=8.319..8.320 rows=1 loops=1)
                                               Filter: (status = 'refuse'::text)
                                       InitPlan 3 (returns $2)
                                         ->  CTE Scan on stats1  (cost=0.00..0.04 rows=1 width=8) (actual time=0.002..0.002 rows=1 loops=1)
                                               Filter: (status = 'facturable'::text)
                             Total runtime: 8.379 ms
                            

                            • Partager sur Facebook
                            • Partager sur Twitter
                            Anonyme
                              26 novembre 2010 à 13:52:30

                              Les CTE permettent de découper une requête "complexe" en plusieurs petites requêtes, pour réellement simplifier l'écriture de requête.

                              Je dirais plutôt que ça ressemble plus à la définition de vues, plutôt que de tables temporaires.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                29 novembre 2010 à 11:16:11

                                Si j'fais le calcul en php, comment je vais faire pour différencier le count(refuse) et le count(facturable) ?


                                <?php
                                $requete2 = "SELECT count(*) AS cnt FROM matable WHERE status IN ('refuse','facturable') GROUP BY status";
                                		$rep2 = mysql_query($requete2);
                                		while($donnees2 = mysql_fetch_assoc($rep2))
                                		{
                                			$count = $donnees2['cnt'];					
                                			echo "$count <br/><br/>";
                                		}
                                
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  29 novembre 2010 à 14:31:04

                                  IL faut que tu récupères aussi le statut calculé ! Sinon c'est clair que tu ne peux pas faire la différence...
                                  $requete2 = "SELECT status, count(*) AS cnt FROM matable WHERE status IN ('refuse','facturable') GROUP BY status"; 
                                  

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    29 novembre 2010 à 14:55:00

                                    Désolé, j'ai pas trop compris.
                                    J'veux faire mon calcul en php, le problème est que je ne sais pas comment différencier les deux count dans la requête ou dans le script.
                                    Par exemple, calcul => count(refuse) / count(facturable).
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      29 novembre 2010 à 17:00:01

                                      Oui, mon code allait dans ce sens. En voici un plus complet pour exprimer plus précisément ce à quoi je pensais :
                                      $requete2 = "SELECT status, count(*) AS cnt FROM matable WHERE status IN ('refuse','facturable') GROUP BY status"; 
                                      $re = mysql_query($requete2);
                                      while ($row=mysql_fetch_assoc($re)) ${$row['status']}=floor($row['cnt']);
                                      echo "refuse=$refuse, facturable=$facturable";
                                      

                                      Ca serait mieux en POO avec PDO et sans variables variables, mais ça marche.

                                      EDIT: par contre la coloration n'a visiblement pas marché elle
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        30 novembre 2010 à 12:19:55

                                        Et simplement
                                        select 100 * refuse / (refuse + facturable) from
                                        (
                                        select	(select count(*) from t1 where status = 'refuse') refuse,
                                        	(select count(*) from t1 where status = 'facturable') facturable
                                        ) _t
                                        


                                        ?
                                        Tracker.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          30 novembre 2010 à 14:38:51

                                          @Tracker: ça fait quand même pas mal de sous-requêtes j'ai l'impression...
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            30 novembre 2010 à 15:20:21

                                            Citation : QuentinC 2

                                            @Tracker: ça fait quand même pas mal de sous-requêtes j'ai l'impression...



                                            Ben 2, le résultat pourrait être récupéré avec un seul parcours au prix de l'utilisation de sum(if...) mais je pense pas que ça puisse accélerer les choses...


                                            Tracker.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              1 décembre 2010 à 13:30:56

                                              Merci pour vos aides.
                                              J'ai encore une question. J'ai un champ nommé date dans maTable, et je souhaite calculer le taux pour chaque mois.

                                              Voici le code :
                                              <?php
                                              $requete2 = "SELECT status, month(date) as mois, count(*) AS cnt FROM maTable 
                                                           WHERE status IN ('refuse','facturable') GROUP BY status, month(date) ORDER BY month(date)"; 
                                              
                                              $re2 = mysql_query($requete2);
                                              while ($row2=mysql_fetch_assoc($re2)) 
                                              {
                                                 ${$row2['status']}=floor($row2['cnt']);
                                                  echo "$mois : refuse=$refusé, facturable=$facturable<br/><br/>";
                                              }
                                              ?>
                                              



                                              Le problème j'obtiens ce genre de résultat pour le mois de janvier :
                                              Image utilisateur
                                              Comment dois-je procéder ? Dois-je changer la requête ?



                                              Note : le calcul du taux se fait en php
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                1 décembre 2010 à 15:18:24

                                                Donne la structure de ta table et des infos qu'on puisse tester des requêtes.

                                                Tracker.
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  1 décembre 2010 à 15:35:06

                                                  Voici la table :

                                                  maTable
                                                  - id
                                                  - status (facturable, refusé)
                                                  - date (YYYY / mm / jj)
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    1 décembre 2010 à 15:38:08

                                                    Tu confonds les lignes et les colonnes, comme ta requête retourne un résultat par ligne, fais :

                                                    <?php
                                                    $requete2 = "SELECT status, month(date) as mois, count(*) AS cnt FROM maTable 
                                                                 WHERE status IN ('refuse','facturable') GROUP BY status, month(date) ORDER BY month(date)"; 
                                                    
                                                    $re2 = mysql_query($requete2);
                                                    
                                                    $info = array();
                                                    
                                                    while ($row2=mysql_fetch_assoc($re2)) 
                                                       $info[$mois][$row2['status']] = $row2['cnt'];
                                                    ?>
                                                    


                                                    Ensuite tu peux simplement lister dans le format que tu veux (et qui ne dépend pas de la requête puisque le but d'une requête SQL n'est jamais de faire de la mise en page) :

                                                    <?php
                                                    foreach( $info as $mois => $comptes )
                                                       echo "$mois : refuse=".$comptes['refusé'].", facturable=".$comptes['facturable']."<br/><br/>";
                                                    



                                                    Note : le calcul du taux se fait en php</citation>
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      3 décembre 2010 à 14:36:52

                                                      Je te remercie pour ton aide.
                                                      Je veux faire la somme de toutes les commissions pour chaque mois.
                                                      Voici ma requête (j'ai rajouté sum(commission) )

                                                      SELECT status, month(date) as mois, sum(commission) as comm, count(*) AS cnt FROM maTable
                                                      WHERE status IN ('refuse','facturable') 
                                                      GROUP BY status, month(date) ORDER BY month(date)
                                                      


                                                      Comment vais-je faire pour afficher la somme dans le foreach sachant qu'il y a déjà le count(refuse) et le count(facturable) ?

                                                      maTable
                                                      - id
                                                      - status (facturable, refusé)
                                                      - date (YYYY / mm / jj)
                                                      - commission (type float)
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        4 décembre 2010 à 8:44:19

                                                        De la même façon : sauf que tu classes les lignes entières dans un array [ mois ][ status ] pour les retrouver facilement

                                                        <?php
                                                        while ($row2=mysql_fetch_assoc($re2)) 
                                                           $info[$mois][$row2['status']] = $row2;
                                                        ?>
                                                        


                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          6 décembre 2010 à 0:03:57

                                                          J'ai fait ce que tu m'as dit, j'obtiens un message d'erreur :

                                                          Fatal error: Unsupported operand types
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            7 décembre 2010 à 0:07:57

                                                            Quelqu'un pour m'aider s'il vous plaît ?
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter

                                                            Server has gone away

                                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                            • Editeur
                                                            • Markdown