2012-09-27 2 views
4

J'ai un système de messagerie personnel sur mon site, ce qui est assez facile. Mais je voudrais avoir une page d'administrateur où toutes les conversations sont montrées entre les utilisateurs et leur quantité de messages.Comment cross-grouper sur deux colonnes en SQL?

Donc, la table ressemble (version simplifiée):

CREATE TABLE pm (
    id  INT(10)  NOT NULL AUTO_INCREMENT, 
    from  INT(10)  NOT NULL REFERENCES (usertable), 
    to  INT(10)  NOT NULL REFERENCES (usertable), 
    message BLOB  NOT NULL 
); 

Exemple:

Dire que j'ai certains utilisateurs: Mark, John, Bryan et Kate.

Mark (from) envoie 5 messages à John (to) et John (from) envoie 3 messages à Mark (to).

Kate (à partir de) envoie 2 messages à Bryan (à) et Bryan (à partir de) envoie 1 message à Kate (à).

Je voudrais un ensemble de résultats qui montre

Mark - John - 8 messages

Kate - Bryan - 3 messages

Et ceci pour tous les utilisateurs de ma table à la fois .

Je suis vraiment bloqué à ce sujet et j'ai cherché partout, mais je n'ai pas trouvé de solution. La difficulté réside dans le fait que je veux tous les utilisateurs répertoriés et je dois traverser la colonne "de" et "à" en quelque sorte ...

J'espère que tout le monde sera en mesure d'aider. Merci d'avance.

Répondre

3
select from_id, to_id, count(*) count_between 
from 
(
    select from_id, to_id from pm 
    union all 
    select to_id, from_id from pm 
) combined 
where from_id < to_id 
group by from_id, to_id 

Échantillon complet

CREATE TABLE pm (from_id int,to_id int); 
insert pm select 1,2; 
insert pm select 1,2; 
insert pm select 1,2; 
insert pm select 1,2; 
insert pm select 1,2; 
insert pm select 2,1; 
insert pm select 2,1; 
insert pm select 2,1; 
insert pm select 3,4; 
insert pm select 3,4; 
insert pm select 4,3; 

select from_id, to_id, count(*) count_between 
from 
(
    select from_id, to_id from pm 
    union all 
    select to_id, from_id from pm 
) combined 
where from_id < to_id 
group by from_id, to_id 

--- results 
from_id  to_id  count_between 
----------- ----------- ------------- 
1   2   8 
3   4   3 

Pour activer les ID dans les noms, utilisez la normale à la table user ou une telle. par exemple.

select u1.name from_, u2.name to_, count(*) count_between 
from 
(
    select from_id, to_id from pm 
    union all 
    select to_id, from_id from pm 
) combined 
join users u1 on u1.id = combined.from_id 
join users u2 on u2.id = combined.to_id 
where from_id < to_id 
group by u1.name, u2.name 
+0

Merci beaucoup! Tu as fait ma journée! :) – LMoeyaert

0

Vous pouvez créer une paire de conversations unique en répertoriant d'abord la personne ayant le plus grand identifiant. Ensuite, vous pouvez groupe par les id des deux personnes:

select ut1.name 
,  ut2.name 
,  convo_pairs.message_count 
from (
     select case when [from] < [to] then [to] else [from] end as p1 
     ,  case when [from] < [to] then [from] else [to] end as p2 
     ,  count(*) as message_count 
     from pm 
     group by 
       case when [from] < [to] then [to] else [from] end as p1 
     ,  case when [from] < [to] then [from] else [to] end as p2 
     ) as convo_pairs 
join usertable ut1 
on  ut1.id = convo_pairs.p1 
join usertable ut2 
on  ut2.id = convo_pairs.p2 
0

Essayez cette

select ISNULL(a.from,b.from) + '-' + ISNULL(a.to,b.to) + '-' + convert(varchar(a.count+b.count)) + 'messages' 
(select pm1.from,pm1.to,count(1) count 
from pm pm1 
group by pm1.from,pm1.to) a FULL OUTER 
(select pm1.from,pm1.to,count(1) count 
from pm pm1 
group by pm1.from,pm1.to) b 
on a.from=b.to 
and a.to=b.from 
Questions connexes