2017-02-15 69 views
0

我有一個「聊天」應用程序,我們在其中有一組用戶之間的聊天。所以一個用戶可以是多個組的一部分。SQL Server選擇記錄的語句分組

一旦用戶登錄,我們必須顯示所有用戶組及其消息。

但是,我們在登錄時爲每個羣組消息都有一個存儲桶/限制爲100條消息。意味着我們只會向每個用戶顯示100條消息(最新消息),並顯示其餘消息中有一個按鈕「加載早期消息」。

但100條短信的這種限制可能低於scenarios-

  1. 我們必須只顯示100條信息(根據桶的大小),如果所有的消息都閱讀各組的基礎上改變。

  2. 我們必須顯示每個組的所有UnRead消息,沒有未讀消息桶。

  3. 而最後一種情況是一些ReadRead & UnRead消息。

    • 如果有> = 100條未讀消息和一些讀消息,我們將只顯示所有的UnRead消息。因爲它(UnRead消息)超過了桶的大小,我們無法在這裏顯示讀取消息。
    • 如果有50條UnRead消息和50條讀取消息,則我們可以顯示所有消息,因爲它不超過存儲桶大小。
    • 如果有60個UnRead和50個讀取消息,那麼我們必須顯示總共100個消息,其中60個消息將是UnRead並且40個將會是Read消息。

所以按照我們必須表明在所有情況下的所有未讀郵件無論是超過桶大小或沒有上述情況。

以下是我們所使用的表格 -

(1)Group表:

GroupId(PK)   GroupName 
    g1      Group_A 
    g2      Group_B 
    g3      Group_C 
    g4      Group_D 
    g5      Group_E 

(2)ChatMessageGroupId是的Fkey這裏)

ChatMessageId(PK) GroupId(FK) Message CreatedDate 
    m1     g1   hi  25 Jan, 2017 
    m2     g2   hi1  26 Jan, 2017 
    m3     g1   hi2  25 Jan, 2017 
    m4     g1   hi3  25 Jan, 2017 
    m5     g3   hi4  27 Jan, 2017 
    m6     g4   hi5  28 Jan, 2017 
    m7     g5   hi6  29 Jan, 2017 
    m8     g2   hi7  26 Jan, 2017 
    m9     g3   hi8  27 Jan, 2017 
    m10     g4   hi9  30 Jan, 2017 

(3)ChatMessageMember(ChatMessageId和的GroupId的是的Fkey在這裏)

MemberId ChatMessageId GroupId UserId ISMessageRead CreatedDate 
cm1    m1  g1  111  Yes   25 Jan, 2017 
cm2    m1  g1  222  Yes   25 Jan, 2017 
cm3    m2  g2  111  No    26 Jan, 2017 
cm4    m2  g2  222  Yes   26 Jan, 2017 
cm5    m3  g1  111  No    25 Jan, 2017 
cm6    m3  g1  222  Yes   25 Jan, 2017 
cm7    m4  g1  111  No    25 Jan, 2017 
cm8    m4  g1  222  Yes   25 Jan, 2017 
cm9    m5  g3  111  Yes   27 Jan, 2017 
cm10    m5  g3  222  Yes   27 Jan, 2017 
cm11    m6  g4  111  No    25 Jan, 2017 
cm12    m6  g4  222  No    25 Jan, 2017 
cm13    m7  g5  111  No    29 Jan, 2017 
cm14    m7  g5  222  No    29 Jan, 2017 
cm15    m8  g2  111  Yes   26 Jan, 2017 
cm16    m8  g2  222  Yes   26 Jan, 2017 
cm17    m9  g3  111  Yes   27 Jan, 2017 
cm18    m9  g3  222  Yes   27 Jan, 2017 
cm19    m10  g4  111  Yes   30 Jan, 2017 
cm20    m10  g4  222  Yes   30 Jan, 2017 

我們使用以下條件來獲得記錄 -

select cmm.* 
from ChatMessageMember cmm 
where UserId = 111 and CreatedDate <= '31 Jan, 2017' 

所以根據上面的查詢記錄應基於「用戶ID」和給出「日期」。在這裏,我們將CreatedDate用作endTime意味着我們必須選擇記錄直到該DateTime。但對於起點,我們有兩個情況下─

  1. 讓我們從結束時間開始這樣的起點將是100的記錄,但如果100記錄爲「未讀」,那麼我們必須選擇的記錄,直到最後的「未讀」紀錄(直到我們沒有得到任何「讀取」記錄)。

  2. 但是,如果我們在第100個位置發現任何「讀取」記錄,那麼它將成爲我們的出發點。

任何人都可以幫我解決這個複雜的場景,我必須關心查詢性能。

僅供參考,我使用SQL Server 2012和VS 2015

更新: 對於輸出請檢查下面scenario-

please check the below table. For ex the bucket/limit is 3 and CreatedDate 
is "30 Jan, 2017". So according to limit and Date filter the messages 
should be m7,m6 & m5 for group 1 (g1). But there is an "UnRead" messages 
ahead after 3 messages (at position m4 & m2). So we have to pick records 
till last "UnRead" message from CreatedDate. Means from m7 to m2. So 
messages will be (m2,m3,m4,m5,m6,m7). 


Message    IsMessageRead   GroupId   CreatedDate 
m1     yes     g1   26 Jan, 2017 
m2     no     g1   27 Jan, 2017 
m3     yes     g1   27 Jan, 2017 
m4     no     g1   27 Jan, 2017 
m5     no     g1   27 Jan, 2017 
m6     yes     g1   27 Jan, 2017 
m7     no     g1   28 Jan, 2017 

回答

0
WITH 
    messages (row_number, memberid, chatmessageid, groupid, userid, ismessageread, createddate) AS 
    (
     SELECT 
      ROW_NUMBER() OVER (ORDER BY ismessageread ASC) rn 
      , memberid 
      , chatmessageid 
      , groupid 
      , userid 
      , ismessageread 
      , createddate 
     FROM 
      ChatMessageMember cmm 
     WHERE 
      UserId = 111 
      AND CreatedDate <= '31 Jan, 2017' 
    ), 
    messages_summary (num_unread) AS 
    (
     SELECT 
      SUM(CASE WHEN ismessageread = 'No' THEN 1 ELSE 0 END) num_unread 
     FROM 
      messages 
    ) 
SELECT 
    * 
FROM 
    messages 
WHERE 
    rn <= (
     SELECT 
      CASE WHEN num_unread > 100 THEN num_unread ELSE 100 END num_messages_to_return 
     FROM 
      messages_summary 
    ) 
+0

我已經更新了我的問題。如果我們在第100個位置發現任何「UnRead」記錄,則有一種情況,那麼我們必須選擇記錄直到我們沒有得到任何「讀取」記錄。這意味着總記錄可能大於100. – Boss

+0

嘗試將'WHERE'子句更改爲'WHERE rn <= 100或ismessageread ='否' –

+0

@boss此答案不提供正在尋找的內容?它會返回符合您指定條件的數據... – user1327961