根据对2个用户ID进行分组获取摘要报告

时间:2015-07-06 19:18:39

标签: sql sql-server

我有一张桌子:

MsgID   MsgrUserID  MsgdUserID  MsgDate     Message 
1          1            4       6/12/2015   Jules - Did you pick up the blueprints?
2          4            1       6/15/2015   Yes, they're in my hands
3          4            1       6/15/2015   Let me know when you can talk
4          3            4       6/16/2015   Jules, let's meet tomorrow
5          1            4       6/17/2015   I'm available at 2 PM today
6          1            3       7/4/2015    Cindy, did you check your mail?
7          4            3       7/3/2015    OK, I'm free after 3PM
8          3            1       7/2/2015    Yes, there was nothing there
9          2            1       7/5/2015    Plan is going well.  Just need more time
10         1            2       7/5/2015    OK, great.  Let me know

我需要做的是获得一份总结所有通信的报告。它看起来像这样:

User: 1
    Correspondence between you and 2: 2      Last correspondence: 7/5/2015
    Correspondence between you and 3: 2      Last correspondence: 7/4/2015
    Correspondence between you and 4: 4      Last correspondence: 6/17/2015

或类似的东西。所以,我需要弄清楚如何总结对应的数量,还要从原始表中获取其他信息。我遇到的问题是,我无法弄清楚如何将总和与原始表相关联,因为它是有条件的。有时,用户的ID位于Msgr(Messenger)字段中,有时它位于Msgd(消息传递)字段中。

我有这个怪物,但我知道#MyMsgs表的连接是错误的所在。

with cte as (
    select 
    MessagedUserID as MessagedUserIDOrig,
    MessagerUserID as MessagerUserIDOrig,
       case when MessagerUserID < MessagedUserID 
            then MessagerUserID else MessagedUserID end MessagerUserID, 
       case when MessagerUserID > MessagedUserID 
            then MessagerUserID else MessagedUserID end MessagedUserID
    from tmpMessaged
)

select MessagerUserID, MessagedUserID, count(*) as Contact 
into #MyMsgs
from cte 
WHERE MessagerUserID = @MyID
    OR MessagedUserID = @MyID
group by MessagerUserID, MessagedUserID


SELECT 
    T1.*, 
    Mgr.UserName as MessagerName, 
    Mgr.UserID as UserID, 
    CASE WHEN T1.MessagedUserID = @MyID THEN Mgd.UserImg1 ELSE Mgr.UserImg1 END as UserImg1, 
    Mgd.UserName as MessagedName,
    CC.Contact,
    Mgd.LastLoginDate as LastOnline,
    CASE WHEN T1.MessagedUserID = @MyID THEN 'Received' ELSE 'Sent' END as LContact,
    LEFT(T1.[Message], 100) + '...' as [uMessage],
    CASE WHEN T1.MessageViewed IS NULL THEN 'No' ELSE 'Yes' END as MsgViewed,
    CASE WHEN T1.MessageFlag IS NULL THEN 'No' ELSE 'Yes' END as MsgFlagged
FROM [dbo].[tmpMessaged] T1
LEFT JOIN [dbo].[tmpUsers] Mgr
ON T1.[MessagerUserID] = Mgr.[UserID]
LEFT JOIN [dbo].[tmpUsers] Mgd
ON T1.[MessagedUserID] = Mgd.[UserID]
LEFT JOIN [dbo].[tmpMessaged] T2
  ON T1.MessageID = T2.MessageID
    LEFT JOIN #MyMsgs CC 
        ON CASE 
      --     WHEN T1.MessagerUserID = @MyID AND CC.MessagerUserID = T1.MessagerUserID THEN 1
           WHEN T1.MessagedUserID = @MyID AND CC.MessagedUserID = T1.MessagedUserID THEN 1
           ELSE 0
           END = 1


WHERE
    -- First grab the records where the User's ID is in the Messaged field
    Mgd.[UserID] = @MyID

UNION

SELECT 
    T1.*, 
    Mgr.UserName as MessagerName, 
    Mgr.UserID as UserID, 
    CASE WHEN T1.MessagerUserID = @MyID THEN Mgr.UserImg1 ELSE Mgd.UserImg1 END as UserImg1, 
    Mgd.UserName as MessagedName,
    CC.Contact,
    Mgd.LastLoginDate as LastOnline,
    CASE WHEN T1.MessagerUserID = @MyID THEN 'Sent' ELSE 'Received' END as LContact,
    LEFT(T1.[Message], 100) + '...' as [uMessage],
    CASE WHEN T1.MessageViewed IS NULL THEN 'No' ELSE 'Yes' END as MsgViewed,
    CASE WHEN T1.MessageFlag IS NULL THEN 'No' ELSE 'Yes' END as MsgFlagged
FROM [dbo].[tmpMessaged] T1
LEFT JOIN [dbo].[tmpUsers] Mgr
ON T1.[MessagerUserID] = Mgr.[UserID]
LEFT JOIN [dbo].[tmpUsers] Mgd
ON T1.[MessagedUserID] = Mgd.[UserID]
LEFT JOIN [dbo].[tmpMessaged] T2
  ON T1.MessageID = T2.MessageID
    LEFT JOIN #MyMsgs CC 
        ON CASE 
           WHEN T1.MessagerUserID = @MyID AND CC.MessagerUserID = T1.MessagerUserID THEN 1
      --     WHEN T1.MessagedUserID = @MyID AND CC.MessagerUserID = T1.MessagedUserID THEN 1
           ELSE 0
           END = 1

WHERE
    -- Now grab the records where the User's ID is in the Messager field
    Mgr.[UserID] = @MyID

ORDER BY T1.MessageDate DESC

3 个答案:

答案 0 :(得分:2)

您可以直接在公用表表达式中进行聚合:

declare @myID int = 1;

with cte as (
    select 
       case when MessagerUserID < MessagedUserID 
            then MessagerUserID else MessagedUserID end MessagerUserID, 
       case when MessagerUserID > MessagedUserID 
            then MessagerUserID else MessagedUserID end MessagedUserID,
       count(*) MessageCount,
       max(MessageDate) LastMessageDate    
    from tmpMessaged
    group by 
       case when MessagerUserID < MessagedUserID 
            then MessagerUserID else MessagedUserID end,
       case when MessagerUserID > MessagedUserID 
            then MessagerUserID else MessagedUserID end
)

select * from cte where MessagerUserID = @myID;

根据您的样本数据,这将导致:

MessagerUserID MessagedUserID MessageCount LastMessageDate    
-------------- -------------- ------------ ---------------
1              2              2            2015-07-05
1              3              2            2015-07-04
1              4              4            2015-06-17

具有标题/详细信息等的特定格式可能在实际的报告应用程序中更好,尽管它当然也可能直接在服务器上进行(但无论如何谁使用SSMS进行漂亮的报告)。

答案 1 :(得分:0)

我问过发件人曾经是接收者并得到了我希望的答案(不)。有了这个规则,你可以&#34;欺骗&#34;并且对记录进行双重堆叠,将参与者1和参与者2交换为其中的一半,然后只关注自己选择该结构并将参与者1视为&#34;您的家伙&#34;和参与者2作为&#34;其他人&#34;。当发送者不能等于接收者时,你永远不会重复计算记录。

DECLARE @UserYouCareAbout int

SET @UserYouCareAbout = 1

SELECT CONVERT(nvarchar(max), GETDATE(), 101)

SELECT
    'Correspondence between you and ' + CONVERT(nvarchar(max), [Message Participant 2]) + ': ' + STR(MAX(MsgDate), 4, 0) AS [Conversation With],
    'Last correspondence: ' + CONVERT(nvarchar(max), MAX(MsgDate), 101) AS [Last Communication]
    /*
    --individual unformatted pieces
    ,
    COUNT(MsgID) AS [MessageCount],
    [Message Participant 2] AS [Other Guy],
    MAX(MsgDate) AS [LastDate]
    */
FROM
    (
        (
        SELECT
            MsgID, 
            MsgrUserID AS [Message Participant 1],
            MsgdUserID AS [Message Participant 2],
            MsgDate
        FROM
            tmpMessaged
        ) --SentStuff
        UNION ALL
        (
        SELECT
            MsgID, 
            MsgdUserID AS [Message Participant 1], --note that
            MsgrUserID AS [Message Participant 2], --these switched
            MsgDate
        FROM
            tmpMessaged
        ) --RecStuff
    ) DerivedAllMessagesTwice
WHERE
    [Message Participant 1] = @UserYouCareAbout
GROUP BY
    [Message Participant 2]

这种简化消除了所有内联条件。

答案 2 :(得分:0)

请尝试以下代码: -

declare @MyID int = 1
create table #yourmsgtable (MsgID  int,  MsgrUserID  int, MsgdUserID  int, MsgDate     date, Message varchar(max))
insert into #yourmsgtable values
(1,1,4,'6/12/2015','Jules - Did you pick up the blueprints?'),
(2,4,1,'6/15/2015','Yes, they''re in my hands'),
(3,4,1,'6/15/2015','Let me know when you can talk'),
(4,3,4,'6/16/2015','Jules, let''s meet tomorrow'),
(5,1,4,'6/17/2015','I''m available at 2 PM today'),
(6,1,3,'7/4/2015','Cindy, did you check your mail?'),
(7,4,3,'7/3/2015','OK, I''m free after 3PM'),
(8,3,1,'7/2/2015','Yes, there was nothing there'),
(9,2,1,'7/5/2015','Plan is going well.  Just need more time'),
(10,1,2,'7/5/2015','OK, great.  Let me know')
create table #tmpmsgtable(party1 int, party2 int, msgdate date)

insert into #tmpmsgtable
select MsgrUserID, MsgdUserID, MsgDate from #yourmsgtable where MsgrUserID = @MyID
union all
select MsgdUserID, MsgrUserID, MsgDate from #yourmsgtable where MsgdUserID = @MyID

select
'User : ' + convert(varchar(max),party1) 'Party 1', 
'Correspondence between you and ' + convert(varchar(max),party2) + ' : ' + convert(varchar(max),count(*)) 'Party 2 Correspondence', 
'Last correspondence : ' + convert(nvarchar(max),max(msgdate)) 'Last correspondence'
from #tmpmsgtable
group by party1, party2

drop table #tmpmsgtable
drop table #yourmsgtable

结果: -

enter image description here