2017-08-05 68 views
2

我想使用SQL Server中的存儲過程合併我的通知數據。我寫了查詢,但在這個查詢中,我得到的不止是多行用戶數據。使用SQL Server將多行合併爲一行?

我想合併關注者通知。比如「用戶a關注用戶b,然後用戶b」就會收到類似「用戶a開始關注你」的通知。再次「用戶c關注用戶b」,然後「用戶b再次收到類似」「用戶c關注你」的通知。

再次「用戶d再次跟隨用戶b,然後用戶b就像獲得通知一樣」。但是現在我想像這樣通知合併:「用戶a,b和另外1個用戶開始關注你」。

這是我的存儲過程:

SELECT 
    N.NotificationId, 
    N.UserId, 
    N.ActionUserId, 
    (CASE WHEN N.NotificationTypeId = 1 THEN 1 
      WHEN N.NotificationTypeId = 7 THEN 3 
     ELSE  
      2 
    END) AS TypeId,       
    AU.ProfileImage, 
    AU.UserName, 
    N.IsRead, 
    (CASE WHEN N.NotificationTypeId = 1 THEN 1 
     WHEN N.NotificationTypeId = 7 THEN 3 
     ELSE 2 
    END) AS TypeId,   
    N.NotificationTypeId, 
    N.InsertDateTime 
FROM 
    Notifications N 
INNER JOIN 
    Users U ON N.UserId = U.UserId 
INNER JOIN 
    Users AU ON N.ActionUserId = AU.UserId  
ORDER BY 
    N.InsertDateTime DESC 

這是我的當前O/P =>

NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime   | ProfileImage 
    6    20  15    hbc  1     2017-06-22 17:14:16.803 20170416032403869.jpeg 
    5    20  16    tyu  1     2017-06-22 17:12:12.297  20170416031522534.jpeg 
    4    20  17    opl  1     2017-06-22 17:11:58.060  20170416031250102.jpeg 
    3    10  11    abc  1     2017-06-22 16:14:16.803 20170416032403867.jpeg 
    2    10  12    xyz  1     2017-06-22 16:14:12.297  20170416031522533.jpeg 
    1    10  13    rty  1     2017-06-22 16:13:58.060  20170416031250101.jpeg 

這是我的例外O/P =>

NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime   | ProfileImage   | NotificationText 
    6    20  15    hbc  1     2017-06-22 17:14:16.803 20170416032403869.jpeg hbc,tyu and 1 other users followed you 
    3    10  11    abc  1     2017-06-22 16:14:16.803 20170416032403867.jpeg abc,xyz and 1 other users followed you 

創建測試數據=>

declare @Notifications table(NotificationID int, UserID int, ActionUserID int, NotificationTypeID int, InsertDateTime datetime); 
declare @Users table(UserID int, UserName nvarchar(10), ProfileImage nvarchar(50)) 
insert into @Notifications values (6,20,15,1,'2017-06-22 17:14:16.803'),(5,20,16,1,'2017-06-22 17:12:12.297'),(4,20,17,1,'2017-06-22 17:11:58.060'),(3,10,11,1,'2017-06-22 16:14:16.803'),(2,10,12,1,'2017-06-22 16:14:12.297'),(1,10,13,1,'2017-06-22 16:13:58.060'); 
insert into @Users values (15,'hbc','20170416032403869.jpeg'),(16,'tyu','20170416031522534.jpeg'),(17,'opl','20170416031250102.jpeg'),(10,'aaa',''),(11,'abc','20170416032403867.jpeg'),(12,'xyz','20170416031522533.jpeg'),(13,'rty','20170416031250101.jpeg'); 
+1

@TimBiegeleisen你能幫我怎麼做才能合併我的數據? – Edit

+1

@marc_s你能幫助我請怎麼做 – Edit

+2

當你問這樣一個問題時,你應該提供:1)CREATE語句所涉及的表,如果沒有所有字段,那麼所有相關字段; 2)INSERT語句用充足的測試數據填充這些表(不需要是真實的數據)來測試結果;以及3)給出測試數據的期望輸出樣本。那麼你有更好的機會獲得幫助。 –

回答

2

試試這個:

declare @Notifications table 
(NotificationID int, 
UserID int, 
ActionUserID int, 
NotificationTypeID int, 
InsertDateTime datetime); 
declare @Users table 
(UserID int, 
UserName nvarchar(10), 
ProfileImage nvarchar(50)) 

insert into @Notifications values 
(6,20,15,1,'2017-06-22 17:14:16.803'), 
(5,20,16,1,'2017-06-22 17:12:12.297'), 
(4,20,17,1,'2017-06-22 17:11:58.060'), 
(3,10,11,1,'2017-06-22 16:14:16.803'), 
(2,10,12,1,'2017-06-22 16:14:12.297'), 
(1,10,13,1,'2017-06-22 16:13:58.060'); 
insert into @Users values (15,'hbc','20170416032403869.jpeg'), 
(16,'tyu','20170416031522534.jpeg'), 
(17,'opl','20170416031250102.jpeg'), 
(10,'aaa',''), 
(20,'bbb',''), 
(11,'abc','20170416032403867.jpeg'), 
(12,'xyz','20170416031522533.jpeg'), 
(13,'rty','20170416031250101.jpeg'); 


declare @followCount table 
(
userid int, 
cnt int 
) 

INSERT INTO @followCount 
select N.UserID, count(*) 
FROM 
    @Notifications N 
INNER JOIN 
    @Users U ON N.UserId = U.UserId 
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId 
GROUP BY n.UserID 

declare @msg table 
(
userid int, 
NotificationMsg varchar(15) 
) 
INSERT INTO @msg 
SELECT DISTINCT N.UserID, Stuff((SELECT ', ' + UserName 
       FROM 
(SELECT UserID, UserName FROM (SELECT N.UserId, 
    AU.UserName, 
    ROW_NUMBER() OVER (PARTITION BY N.UserID ORDER BY N.InsertDateTime DESC) as rn 
    FROM 
    @Notifications N 
INNER JOIN 
    @Users U ON N.UserId = U.UserId 
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId 
INNER JOIN 
    @followCount C on C.userid = N.UserID) t2 WHERE rn < 3) t2 
    WHERE t2.UserID = N.UserID 
       FOR XML PATH('')), 1, 2, '') AS NotificationMsg 
FROM @Notifications N 

; with cte as  
(SELECT N.NotificationId, 
     N.UserId, 
     N.ActionUserId, 
     (CASE WHEN N.NotificationTypeId = 1 THEN 1 
      WHEN N.NotificationTypeId = 7 THEN 3 
     ELSE  
      2 
     END) AS TypeId,       
     AU.ProfileImage, 
     AU.UserName, 
     N.NotificationTypeId, 
     N.InsertDateTime, 
     m.NotificationMsg + CASE WHEN c.cnt > 2 THEN ' + ' 
     + FORMAT(c.cnt - 2, '0') + ' other users' END + ' followed you.' AS NotificationText, 
     ROW_NUMBER() OVER (PARTITION BY N.UserID ORDER BY N.InsertDateTime DESC) as rn 
FROM 
    @Notifications N 
INNER JOIN 
    @Users U ON N.UserId = U.UserId 
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId 
INNER JOIN 
    @followCount C on C.userid = N.UserID 
INNER JOIN @msg M ON m.userid = N.UserID) 

SELECT NotificationID, UserID, ActionUserID, UserName, 
NotificationTypeID, InsertDateTime, ProfileImage, NotificationText 
FROM cte WHERE rn = 1 

請注意,我不得不添加一個條目的用戶ID 20.你給我的樣本數據只生產了一個記錄。

是什麼讓它特別棘手,是需要兩個名字加x個其他。這涉及幾個中間步驟。很可能有人比SQL更擅長於縮短這一點。另請注意,我只用此數據進行過測試。您需要檢查數量大於和小於3的其他用戶,以確保它們仍然很好。