2015-07-06 2 views
2

У меня есть таблица, как, например:Получение сводного отчета на основе группирования 2 логинов

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 

Или что-то в этом роде. Итак, мне нужно выяснить, как суммировать количество корреспонденций, а также получать другие части информации из исходной таблицы. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как связать сумму с исходной таблицей, потому что она условна. Иногда идентификатор пользователя находится в поле Msgr (Messenger), а иногда он находится в поле Msgd (Messaged).

У меня есть этот монстр, но я знаю, что соединение с таблицей #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 
+0

ли вы когда-нибудь есть сценарий, где пользователь сам сообщений? то есть MsgrUserID = MsgdUserID в записи? – LDMJoe

+0

Нет, этого никогда не произойдет. –

+0

Некоторые дружеские советы: люди могут быть более склонны помочь вам, если вы признаете помощь, которую вы получаете. Просто говорю, так как я вижу, что вы включили код из моего ответа на свой последний вопрос здесь, и это остается открытым. – jpw

ответ

0

Я спросил о том, что отправитель когда-либо был получателем, и получил ответ, на который я надеялся (нет). Используя это правило, вы можете «обмануть» и дважды уложить записи, обменивая участника 1 и участника 2 по половине из них, тогда только заботиться о том, чтобы выбрать из этой структуры и рассматривать участника 1 как «своего парня» и участника 2 как «другой парень». Вы никогда не будете дважды считать запись, когда отправитель не сможет равняться получателю.

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

Вы можете просто сделать агрегацию непосредственно в общем табличном выражении:

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 для хороших отчетов в любом случае).

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