2017-08-05 67 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的其他用户,以确保它们仍然很好。