2011-07-12 5 views
3

J'ai 3 instructions SELECT Je voudrais combiner en un seul:combinant plusieurs comptes en une seule requête - par groupe

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B 
     ON A.userid = B.userid 
WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname 

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B 
     ON A.userid = B.userid 
WHERE status = 'C' 
AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname` 

SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname 
FROM feedbacks A 
    INNER JOIN users B ON A.userid = B.userid 
WHERE caused_change = 1 
AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
GROUP BY fullname 

Mais les combiner semble toujours retourner une erreur: (Opérande doit contenir 1 colonne (s))

SELECT 
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T1, 
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T2, 
(SELECT COUNT(A.id), CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname) AS T3 

J'ai donc essayé de retirer le JOIN et GROUP des déclarations individuelles à faire:

SELECT CONCAT(B.fname, ' ', B.lname) AS fullname, 
(SELECT COUNT(A.id) FROM feedbacks A WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T1, 
(SELECT COUNT(A.id) FROM feedbacks A WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T2, 
(SELECT COUNT(A.id) FROM feedbacks A WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11') AS T3 
FROM feedbacks 
    INNER JOIN users B 
     ON feedbacks.userid = B.userid 
GROUP BY fullname 

Mais t hat renvoie les totaux pour tout, par rapport à la répartition par utilisateur (parce que les comptes ne disent rien à propos de userid ou fullname dans la clause where, sans doute). Je me sens comme si je suis proche mais manque quelque chose. Quelqu'un peut-il me pointer dans la bonne direction ici? J'essaie juste d'apprendre ce que je fais de mal.

Nous vous remercions de votre temps.

Répondre

7

La meilleure façon est d'utiliser un SUM conditionnel:

SELECT CONCAT(B.fname, ' ', B.lname) AS fullname, 
     SUM(
      CASE WHEN DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
      THEN 1 ELSE 0 END 
     ) AS T1, 
     SUM(
      CASE WHEN status = 'C' 
       AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
      THEN 1 ELSE 0 END 
     ) AS T2, 
     SUM(
      CASE WHEN caused_change = 1 
       AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
      THEN 1 ELSE 0 END 
     ) AS T3 
FROM feedbacks 
    INNER JOIN users B 
     ON feedbacks.userid = B.userid 
GROUP BY fullname 
+0

Merci, Scorpi0 (et aussi pour l'édition). – greatcaesarsghost

+0

Merci! Cela s'est avéré être super utile aujourd'hui. –

+0

Légende les gars cela m'a sauvé un moment sérieux aujourd'hui. à votre santé!!. – jiraiya

0

Je ne sais pas si vous pouvez combiner ces 3 requêtes en une seule requête unifiée. Vous avez 3 « où les clauses » qui se chevauchent:

première requête: tous les enregistrements qui tombent dans la plage de dates
seconde requête: tous les enregistrements qui tombent dans la plage de dates, mais ont également le statut = « C »
troisième requête: TOUS les enregistrements qui tombent dans la plage de dates mais aussi have_change = 1

En termes logiques, la première requête contient déjà tous les enregistrements des deuxième et troisième requêtes, donc vous compteriez deux fois les résultats de # 2 et # 3.

Cependant, si vous ne voulez combiner les trois en un seul résultat, puis faire la méthode de requête externe:

SELECT sum(cnt), fullname 
FROM (
    SELECT COUNT(A.id) as cnt, CONCAT(B.fname,' ', B.lname) AS fullname 
    FROM feedbacks A 
    INNER JOIN users B ON A.userid = B.userid 
    WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
    GROUP BY fullname 

    UNION 

    ... 
    WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 

    UNION 

    ... 
    WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' 
) AS innerquery 
GROUP BY fullname 

Notez l'alias sur la count() dans la première requête interne. Cela fait apparaître le champ compté comme 'cnt' pour la requête externe.

+0

J'attrapait déjà tous les résultats pour cette plage de dates et d'utiliser PHP pour exécuter la logique et compte . Il m'a été suggéré que je devrais laisser le db faire le gros du travail. Merci d'avoir pris le temps d'expliquer. – greatcaesarsghost

0

UNION et SUM devraient faire le travail. Votre code devrait ressembler à ceci:

select sum(x.col1), x.fullname 
from 
(SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname 
UNION 
SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE status = 'C' AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname 
UNION 
SELECT COUNT(A.id)as col1, CONCAT(B.fname,' ', B.lname) AS fullname FROM feedbacks A INNER JOIN users B ON A.userid = B.userid WHERE caused_change = 1 AND DATE(origindate) BETWEEN '2011-03-01' AND '2011-07-11' GROUP BY fullname 
)x 
group by x.fullname 
Questions connexes