4

我的网站上有一个个人消息系统,这很容易。但我想要一个管理员页面,其中显示用户之间的所有对话及其消息量。

所以表格看起来像(简化版):

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
);

例子:

假设我有一些用户:Mark、John、Bryan 和 Kate。

Mark (from) 向 John (to) 发送 5 条消息,John (from) 向 Mark (to) 发送 3 条消息。

Kate(发件人)向 Bryan(收件人)发送 2 条消息,Bryan(发件人)向 Kate(收件人)发送 1 条消息。

我想要一个显示的结果集

马克 - 约翰 - 8 条信息

凯特 - 布莱恩 - 3 条信息

这适用于我表中的所有用户。

我真的坚持这一点,我到处搜索,但没有找到解决方案。困难在于我希望列出所有用户并且我必须以某种方式跨越“从”和“到”列......

我希望任何人都能够提供帮助。提前致谢。

4

3 回答 3

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

完整样本

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

要将 ID 转换为名称,请使用普通的 to usertable 或类似的东西。例如

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
于 2012-09-27T06:39:18.293 回答
0

您可以通过首先列出具有最大 id 的人来使对话对独一无二。然后你可以按两个人的 id 分组:

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
于 2012-09-27T06:35:11.740 回答
0

试试这个

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
于 2012-09-27T06:41:47.023 回答