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.
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;
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 ...
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
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/>";
}
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).
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
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: ç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...
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 :
Comment dois-je procéder ? Dois-je changer la requête ?
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) :
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)
× 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.
Tutoriel complet MySQL !
Tutoriel complet MySQL !
Tutoriel complet MySQL !